[med-svn] [fis-gtm] 01/03: Imported Upstream version 6.2-000
Amul Shah
tuskentower-guest at moszumanska.debian.org
Wed Sep 24 04:11:44 UTC 2014
This is an automated email from the git hooks/post-receive script.
tuskentower-guest pushed a commit to branch master
in repository fis-gtm.
commit d5b4b2c01fa603979637bac37a55b49db56e11d8
Author: Amul Shah <Amul.Shah at fisglobal.com>
Date: Sun Sep 21 23:00:44 2014 -0400
Imported Upstream version 6.2-000
---
CMakeLists.txt | 136 +-
LICENSE | 2 +-
README | 24 +-
sr_avms/fetch_all.m64 | 41 +
sr_avms/op_extjmp.m64 | 6 +-
sr_avms/release_name.h | 4 +-
sr_i386/cmerrors_ctl.c | 2 +-
sr_i386/cmierrors_ctl.c | 2 +-
sr_i386/error.si | 10 +-
sr_i386/gdeerrors_ctl.c | 2 +-
sr_i386/incr_link.c | 48 +-
sr_i386/merrors_ansi.h | 49 +-
sr_i386/merrors_ctl.c | 114 +-
sr_i386/obj_file.c | 45 +-
sr_i386/op_extjmp.s | 6 +-
sr_i386/ttt.c | 1357 +-
sr_linux/gtm_env_sp.csh | 8 +-
sr_linux/gtm_env_sp.mk | 182 -
sr_linux/gtm_getenv.c | 18 +-
sr_linux/platform.cmake | 7 +-
sr_linux/release_name.h | 12 +-
sr_port/advancewindow.c | 23 +-
sr_port/alias.h | 368 +-
sr_port/alias_funcs.c | 303 +-
sr_port/anticipatory_freeze.h | 24 +-
sr_port/bx_boolop.c | 125 +-
sr_port/cert_blk.c | 10 +-
sr_port/cmd.c | 12 +-
sr_port/cmd.h | 6 +-
sr_port/cmd_qlf.h | 9 +-
sr_port/code_gen.c | 17 +-
...{gtm_imagetype_init.c => common_startup_init.c} | 72 +-
.../common_startup_init.h | 9 +-
sr_port/compiler.h | 20 +-
sr_port/compiler_startup.c | 53 +-
sr_port/cre_jnl_file.c | 9 +-
sr_port/cre_jnl_file_intrpt_rename.c | 75 +-
sr_port/cre_private_code_copy.c | 16 +-
sr_port/dbcertify.c | 9 +-
sr_port/deviceparameters.c | 47 +-
sr_port/do_xform.h | 3 +-
sr_port/dse.h | 200 +-
sr_port/dse.hlp | 129 +-
sr_port/dse_adrec.c | 122 +-
sr_port/dse_adstar.c | 42 +-
sr_port/dse_b_dmp.c | 52 +-
sr_port/dse_cache.c | 64 +-
sr_port/dse_chng_bhead.c | 126 +-
sr_port/dse_chng_fhead.c | 18 +-
sr_port/dse_chng_rhead.c | 46 +-
sr_port/dse_exhaus.c | 25 +-
sr_port/dse_f_blk.c | 101 +-
sr_port/dse_f_free.c | 29 +-
sr_port/dse_f_reg.c | 33 +-
sr_port/dse_fdmp.c | 122 +-
sr_port/dse_getblk.c | 52 +
sr_port/dse_getki.c | 13 +-
sr_port/dse_integ.c | 34 +-
sr_port/dse_is_blk_free.c | 21 +-
sr_port/dse_is_blk_in.c | 16 +-
sr_port/dse_ksrch.c | 25 +-
sr_port/dse_maps.c | 177 +-
sr_port/dse_order.c | 17 +-
sr_port/dse_over.c | 83 +-
sr_port/dse_r_dmp.c | 50 +-
sr_port/dse_range.c | 79 +-
sr_port/dse_rest.c | 132 +-
sr_port/dse_rmrec.c | 52 +-
sr_port/dse_rmsb.c | 83 +-
sr_port/dse_save.c | 57 +-
sr_port/dse_shift.c | 38 +-
sr_port/entryref.c | 383 +-
sr_port/error.h | 17 +-
sr_port/error_trap.h | 3 +-
sr_port/exfunc.c | 4 +-
sr_port/expritem.c | 14 +-
sr_port/ext2jnl.c | 119 +-
sr_port/f_zsearch.c | 11 +-
sr_port/f_zsocket.c | 85 +
sr_port/fao_parm.h | 29 +-
sr_port/fntext_ch.c | 23 +-
sr_port/format_targ_key.c | 7 +-
sr_port/fullbool.h | 14 +-
sr_port/gbldefs.c | 18 +-
sr_port/gde.hlp | 965 +-
sr_port/gdeshow.m | 23 +-
sr_port/gdsblk.h | 41 +-
sr_port/gdsfhead.h | 22 +-
sr_port/get_cmd_qlf.c | 8 +-
sr_port/get_dlr_zkey.c | 26 +-
sr_port/goframes.c | 11 +-
sr_port/gtm_common_defs.h | 26 +-
sr_port/gtm_ctype.h | 13 +-
sr_port/gtm_env_init.c | 33 +-
sr_port/gtm_fetch.c | 39 +-
sr_port/gtm_limits.h | 13 +-
sr_port/gtm_newintrinsic.c | 21 +-
sr_port/gtm_rename.h | 3 +-
sr_port/gtm_savetraps.c | 9 +-
sr_port/gtm_threadgbl_defs.h | 32 +-
sr_port/gtm_threadgbl_deftypes.c | 7 +-
sr_port/gtm_threadgbl_init.c | 7 +-
sr_port/gtm_un.h | 6 +-
sr_port/gtmimagename.h | 4 +-
sr_port/gtmimagetable.h | 3 +-
sr_port/gtmrecv_helpers_init.c | 29 +-
sr_port/gtmrecv_upd_proc_init.c | 27 +-
sr_port/gtmsource_ctl_init.c | 18 +-
sr_port/gv_rundown.c | 9 +-
sr_port/gv_xform_key.c | 7 +-
sr_port/gvcst_init.c | 41 +-
sr_port/gvcst_put.c | 13 +-
sr_port/gvcst_search.c | 35 +-
sr_port/gvstrsub.c | 60 -
sr_port/gvsub2str.c | 32 +-
sr_port/gvsub2str.h | 4 +-
sr_port/gvzwr_fini.c | 15 +-
sr_port/gvzwr_var.c | 5 +-
sr_port/indir.h | 6 +-
sr_port/insert_region.c | 18 +-
sr_port/io.h | 21 +-
sr_port/io_dev_dispatch.h | 6 +-
sr_port/io_init.c | 121 +-
sr_port/io_init_ch.c | 4 +-
sr_port/iop.h | 12 +-
sr_port/iormdefsp.h | 8 +-
sr_port/iosocket_bind.c | 18 +-
sr_port/iosocket_close.c | 38 +-
sr_port/iosocket_connect.c | 49 +-
sr_port/iosocket_create.c | 124 +-
sr_port/iosocket_flush.c | 17 +-
sr_port/iosocket_handle.c | 9 +-
sr_port/iosocket_iocontrol.c | 140 +-
sr_port/iosocket_open.c | 114 +-
sr_port/iosocket_readfl.c | 50 +-
sr_port/iosocket_use.c | 164 +-
sr_port/iosocket_wait.c | 86 +-
sr_port/iosocket_write.c | 80 +-
sr_port/iosocket_wteol.c | 15 +-
sr_port/iosocket_wtff.c | 18 +-
sr_port/iosocketdef.h | 78 +-
sr_port/is_file_identical.h | 4 +-
sr_port/jnl.h | 162 +-
sr_port/jnl2ext.c | 70 +-
sr_port/jnl_file_close.c | 58 +-
sr_port/jnl_file_lost.c | 18 +-
sr_port/jnl_file_open_common.c | 4 +-
sr_port/jnl_file_open_switch.c | 4 +-
sr_port/jnl_format.c | 15 +-
sr_port/jnl_rec_table.h | 61 +-
sr_port/jnl_typedef.h | 89 +-
sr_port/jnl_write.c | 191 +-
sr_port/jnl_write_eof_rec.c | 4 +-
sr_port/jnl_write_epoch_rec.c | 13 +-
sr_port/jnl_write_logical.c | 10 +-
sr_port/jnl_write_poolonly.c | 10 +-
sr_port/lastchance1.c | 6 +-
sr_port/lclcol.mpt | 40 +-
sr_port/lke.hlp | 4 +-
sr_port/lookup_variable_htent.c | 14 +-
sr_port/lv_getslot.c | 20 +-
sr_port/lv_kill.c | 9 +-
sr_port/lv_killarray.c | 5 +-
sr_port/lv_newblock.c | 3 +-
sr_port/lv_newname.c | 31 +-
sr_port/lv_tree.c | 30 +-
sr_port/lv_tree.h | 8 +-
sr_port/lv_val.h | 184 +-
sr_port/lv_var_clone.c | 15 +-
sr_port/lvzwr_fini.c | 6 +-
sr_port/lvzwr_out.c | 7 +-
sr_port/lvzwr_var.c | 9 +-
sr_port/m_break.c | 8 +-
sr_port/m_do.c | 4 +-
sr_port/m_new.c | 28 +-
sr_port/m_zhalt.c | 26 +-
sr_port/md5_digest2hex.c | 40 +
sr_port/{dse_is_blk_free.h => md5_digest2hex.h} | 13 +-
sr_port/mdb_condition_handler.c | 182 +-
sr_port/mdef.h | 6 +-
sr_port/merge_desc_check.c | 49 +-
sr_port/merrors.msg | 65 +-
sr_port/mu_extr_gblout.c | 12 +-
sr_port/mu_int_blk.c | 27 +-
sr_port/mu_int_init.c | 11 +-
sr_port/mu_int_reg.c | 37 +-
sr_port/{mur_interactive.c => mu_interactive.c} | 29 +-
sr_port/{gtm_imagetype_init.h => mu_interactive.h} | 9 +-
sr_port/mu_reorg.c | 5 +-
sr_port/mubfndreg.c | 53 -
sr_port/muext_rec_table.h | 5 +-
sr_port/muextr.h | 36 +-
sr_port/mumps.hlp | 15921 +++++++++++--------
sr_port/mupfndfil.c | 18 +-
sr_port/mupint.h | 14 +-
sr_port/mupip.hlp | 371 +-
sr_port/mupip_backup.c | 22 +-
sr_port/mupip_create.c | 22 +-
sr_port/mupip_integ.c | 39 +-
sr_port/mupip_io_dev_dispatch.h | 6 +-
sr_port/mupip_recover.c | 6 +-
sr_port/mupip_set_journal.c | 27 +-
sr_port/mupipbckup.h | 10 +-
sr_port/muprec.h | 12 +-
sr_port/mur_back_process.c | 34 +-
sr_port/mur_close_files.c | 19 +-
sr_port/mur_db_files_from_jnllist.c | 19 +-
sr_port/mur_forward.c | 7 +-
sr_port/mur_forward_play_cur_jrec.c | 14 +-
sr_port/mur_jnl_ext.c | 16 +-
sr_port/mur_open_files.c | 69 +-
sr_port/mur_output_record.c | 44 +-
sr_port/mur_put_aimg_rec.c | 30 +-
sr_port/mur_read_file.c | 46 +-
sr_port/mur_validate_checksum.c | 5 +-
sr_port/mval2fao.c | 201 +-
sr_port/nil_iocontrol.c | 4 +-
sr_port/objlabel.h | 4 +-
sr_port/op.h | 13 +-
sr_port/op_bindparm.c | 4 +-
sr_port/op_clralsvars.c | 3 +-
sr_port/op_exfunret.c | 18 +-
sr_port/op_exp.c | 19 +-
sr_port/op_fnname.c | 14 +-
sr_port/op_fntext.c | 14 +-
sr_port/op_fnview.c | 44 +-
sr_port/{dse_is_blk_free.h => op_fnzsearch.h} | 12 +-
sr_port/op_fnzsocket.c | 400 +
sr_port/op_gvnext.c | 7 +-
sr_port/op_gvorder.c | 7 +-
sr_port/op_halt.c | 6 +-
sr_port/op_iocontrol.c | 88 +-
sr_port/op_killalias.c | 13 +-
sr_port/op_killaliasall.c | 37 +-
sr_port/op_merge.c | 110 +-
sr_port/op_merge_arg.c | 26 +-
sr_port/op_newintrinsic.c | 44 +-
sr_port/op_newvar.c | 76 +-
sr_port/op_putindx.c | 77 +-
sr_port/op_rhdaddr.c | 23 +-
sr_port/op_rterror.c | 28 +-
sr_port/op_savlvn.c | 3 +-
sr_port/op_setals2als.c | 8 +-
sr_port/op_setalsct2alsct.c | 15 +-
sr_port/op_setalsctin2als.c | 18 +-
sr_port/op_setalsin2alsct.c | 3 +-
sr_port/op_setfnretin2als.c | 8 +-
sr_port/op_setfnretin2alsct.c | 3 +-
sr_port/op_setzbrk.c | 6 +-
sr_port/op_stoglvn.c | 10 +-
sr_port/op_svput.c | 10 +-
sr_port/op_tcommit.c | 40 +-
sr_port/op_tstart.c | 93 +-
sr_port/op_unwind.c | 23 +-
sr_port/op_view.c | 59 +-
sr_port/op_xkill.c | 16 +-
sr_port/op_xnew.c | 123 +-
sr_port/op_zhalt.c | 6 +-
sr_port/op_zprevious.c | 5 +-
sr_port/op_zshow.c | 12 +-
sr_port/opcode_def.h | 7 +-
sr_port/outofband.h | 9 +-
sr_port/outofband_action.c | 31 +-
sr_port/patstr.c | 14 +-
sr_port/print_target.c | 7 +-
sr_port/randstr.mpt | 6 +-
sr_port/release_private_code_copy.c | 21 +-
sr_port/repl_comm.h | 4 +-
sr_port/repl_ctl.h | 11 +-
sr_port/repl_dbg.h | 3 +-
sr_port/repl_filter.c | 998 +-
sr_port/repl_filter.h | 107 +-
sr_port/repl_sort_tr_buff.c | 15 +-
sr_port/replic_gbldefs.c | 4 +-
sr_port/resolve_ref.c | 24 +-
sr_port/rwformat.c | 19 +-
sr_port/secshr_db_clnup.c | 39 +-
sr_port/start_for_fetches.c | 33 +-
sr_port/stp_gcol_ch.c | 16 +-
sr_port/stp_gcol_src.h | 141 +-
sr_port/str2gvargs.c | 77 +-
sr_port/stringpool.h | 27 +-
sr_port/symbinit.c | 32 +-
sr_port/t_end.c | 4 +-
sr_port/t_qread.c | 17 +-
sr_port/t_write.c | 19 +-
sr_port/term_setup.h | 4 +-
sr_port/tp.h | 4 +-
sr_port/tp_frame.h | 5 +-
sr_port/tp_restart.c | 15 +-
sr_port/tp_tend.c | 9 +-
sr_port/tp_unwind.c | 156 +-
sr_port/tp_unwind.h | 23 +-
sr_port/trim.mpt | 24 +-
sr_port/unw_mv_ent.c | 8 +-
sr_port/unw_retarg.c | 72 +-
sr_port/updhelper_reader.c | 8 +-
sr_port/updproc.c | 58 +-
sr_port/updproc.h | 11 +-
sr_port/updproc_end.c | 6 +-
sr_port/util_ch.c | 4 +-
sr_port/view_arg_convert.c | 4 +-
sr_port/viewtab.h | 11 +-
sr_port/wbox_test_init.h | 10 +-
sr_port/wcs_recover.c | 48 +-
sr_port/xcmd.mpt | 31 +-
sr_port/xfer.h | 19 +-
sr_port/xfer_enum.h | 14 +-
sr_port/xfer_name.c | 4 +-
sr_port/zbreak.h | 4 +-
sr_port/zlput_rname.c | 133 +-
sr_port/zr_put_free.c | 14 +-
sr_port/{zr_remove.c => zr_remove_zbrks.c} | 9 +-
sr_port/zr_unlink_rtn.c | 150 +
sr_port/{term_setup.h => zr_unlink_rtn.h} | 10 +-
sr_port/zro_init.c | 10 +-
sr_port/zshow_params.h | 3 +-
sr_port/{gtm_imagetype_init.h => zsocket.h} | 20 +-
sr_port/zsockettab.h | 31 +
sr_unix/CMakeLists.txt | 134 +-
sr_unix/Makefile.mk | 8 +-
sr_unix/add_db_key.sh | 66 -
sr_unix/auto_zlink.c | 32 +-
sr_unix/bin_load.c | 74 +-
sr_unix/buildaux.csh | 84 +-
sr_unix/buildshr.csh | 20 +-
sr_unix/check_unicode_support.csh | 28 +-
sr_unix/cli.c | 14 +-
sr_unix/cli_lex.c | 98 +-
sr_unix/cli_parse.c | 30 +-
sr_unix/comlist.csh | 135 +-
sr_unix/comlist.mk | 649 -
sr_unix/configure.gtc | 46 +-
sr_unix/ctrlc_set.c | 27 +-
sr_unix/custom_errors_sample.txt | 1 +
sr_unix/db_ipcs_reset.c | 36 +-
sr_unix/dm_read.c | 52 +-
sr_unix/do_xform.c | 65 +-
sr_unix/dse.c | 16 +-
sr_unix/dse_cmd.c | 3 +-
sr_unix/dse_open.c | 8 +-
sr_unix/errorsp.h | 127 +-
sr_unix/fake_enospc.c | 161 +
sr_avms/release_name.h => sr_unix/fake_enospc.h | 10 +-
sr_unix/fgn_getinfo.c | 40 +-
sr_unix/file_input.c | 46 +-
sr_unix/file_input.h | 7 +-
sr_unix/find_reg_hash_idx.c | 28 +
sr_unix/fork_init.h | 32 +-
sr_unix/ftok.c | 4 +-
sr_unix/gdeverif.m | 3 +-
sr_unix/gds_rundown.c | 35 +-
sr_unix/gds_rundown_ch.c | 18 +-
sr_unix/gds_rundown_err_cleanup.c | 18 +-
sr_unix/gds_rundown_err_cleanup.h | 18 +-
sr_unix/gen_sym_key.sh | 8 +-
sr_unix/gen_xfer_desc.csh | 3 +-
sr_unix/generic_signal_handler.c | 8 +-
sr_unix/get_lib_dirs.mk | 151 -
sr_unix/get_src_line.c | 375 +-
sr_unix/getcaps.c | 127 +-
sr_unix/geteuid.c | 11 +-
sr_unix/go_load.c | 47 +-
sr_unix/grab_crit_immediate.c | 32 +-
sr_unix/grab_lock.c | 15 +-
sr_unix/gt_timers.c | 28 +-
sr_unix/gtm.c | 8 +-
sr_unix/gtm_bintim.c | 5 +-
sr_unix/gtm_c_stack_trace.c | 18 +-
sr_unix/gtm_c_stack_trace_semop.c | 18 +-
sr_unix/gtm_c_stack_trace_semop.h | 18 +-
sr_unix/gtm_cshrc.csh | 27 +-
sr_unix/gtm_env.csh | 3 +-
sr_unix/gtm_env_init_sp.c | 57 +-
sr_unix/gtm_exit_handler.c | 6 +-
sr_unix/gtm_fork_n_core.c | 4 +-
sr_unix/gtm_logicals.h | 12 +-
sr_unix/gtm_main.c | 15 +-
sr_unix/gtm_pipe.c | 4 +-
sr_unix/gtm_putmsg.c | 6 +-
sr_unix/gtm_startup.c | 13 +-
sr_unix/gtm_startup_chk.c | 165 +-
sr_unix/gtm_startup_chk.h | 13 +-
sr_unix/gtm_system.c | 18 +-
sr_unix/gtm_test_install.csh | 8 +-
sr_unix/gtm_tls_impl.c | 32 +-
sr_unix/gtm_tls_impl.h | 4 +-
sr_unix/gtm_tls_interface.h | 32 +-
sr_unix/gtm_tls_loadlibrary.c | 16 +-
sr_unix/gtm_trigger.c | 192 +-
sr_unix/gtm_unique_file_util.c | 7 +-
sr_unix/gtm_unlink_all.c | 69 +-
sr_unix/gtmci.c | 61 +-
sr_unix/gtmcrypt.h | 233 +-
sr_unix/gtmcrypt_dbk_ref.c | 1071 +-
sr_unix/gtmcrypt_dbk_ref.h | 281 +-
sr_unix/gtmcrypt_entry.c | 31 +-
sr_unix/gtmcrypt_funclist.h | 19 +-
sr_unix/gtmcrypt_interface.h | 148 +-
sr_unix/gtmcrypt_pk_ref.c | 49 +-
sr_unix/gtmcrypt_pk_ref.h | 4 +-
sr_unix/gtmcrypt_ref.c | 409 +-
sr_unix/gtmcrypt_ref.h | 15 +-
sr_unix/gtmcrypt_sym_ref.c | 134 +-
sr_unix/gtmcrypt_sym_ref.h | 16 +-
sr_unix/gtmcrypt_util.c | 43 +-
sr_unix/gtmcrypt_util.h | 196 +-
sr_unix/gtmhelp.m | 154 +-
sr_unix/gtminstall.sh | 362 +-
sr_unix/gtminstall_Solaris.sh | 362 +-
sr_unix/gtmio.h | 98 +-
sr_unix/gtmlink.c | 18 +-
sr_unix/gtmlink.h | 18 +-
sr_unix/gtmprofile.gtc | 4 +-
sr_unix/gtmrecv.c | 16 +-
sr_unix/gtmrecv_fetchresync.c | 16 +-
sr_unix/gtmrecv_process.c | 90 +-
sr_unix/gtmsecshr.c | 20 +-
sr_unix/gtmsecshr_sock_init.c | 41 +-
sr_unix/gtmsecshr_wrapper.c | 27 +-
sr_unix/gtmsource.c | 9 +-
sr_unix/gtmsource_end.c | 4 +-
sr_unix/gtmsource_process.c | 19 +-
sr_unix/gtmsource_process_ops.c | 63 +-
sr_unix/gtmsource_readfiles.c | 271 +-
sr_unix/gtmxc_types.h | 6 +-
sr_unix/gv_trigger.c | 7 +-
sr_unix/gvcst_init_sysops.c | 18 +-
sr_unix/heartbeat_timer.c | 157 +-
sr_unix/heartbeat_timer.h | 15 +-
sr_unix/incr_link.c | 666 +-
sr_unix/incr_link.h | 9 +-
sr_unix/io_open_try.c | 96 +-
sr_unix/ioff_open.c | 5 +-
sr_unix/iopi_iocontrol.c | 128 +-
sr_unix/iopi_open.c | 19 +-
sr_unix/iorm_close.c | 90 +-
sr_unix/iorm_get.c | 100 +-
sr_unix/iorm_open.c | 266 +-
sr_unix/iorm_readfl.c | 232 +-
sr_unix/iorm_use.c | 905 +-
sr_unix/iorm_write.c | 256 +-
sr_unix/iorm_wteol.c | 107 +-
sr_unix/iormdef.h | 98 +-
sr_unix/iosocket_pass_local.c | 695 +
sr_unix/iott_edit.c | 75 +-
sr_unix/iott_iocontrol.c | 8 +-
sr_unix/iott_readfl.c | 38 +-
sr_unix/iott_use.c | 147 +-
sr_unix/ious_iocontrol.c | 4 +-
sr_unix/is_file_identical.c | 32 +-
sr_unix/jnl_file_extend.c | 57 +-
sr_unix/jnl_file_open.c | 13 +-
sr_unix/jnlext_write.c | 3 +-
sr_unix/jnlpool_init.c | 114 +-
sr_unix/kitstart.csh | 13 +-
sr_unix/libdse.list | 1 +
sr_unix/libmupip.list | 3 +-
sr_unix/lintgtm.csh | 21 +-
sr_unix/lke.c | 23 +-
sr_unix/lke_ctrlc_handler.c | 18 +-
sr_unix/load.h | 23 +-
sr_unix/m_zrupdate.c | 63 +
sr_unix/memprot.c | 47 +
sr_avms/release_name.h => sr_unix/memprot.h | 11 +-
sr_unix/mu_decrypt.c | 4 +-
sr_unix/mu_extract.c | 67 +-
sr_unix/mu_getlst.c | 30 +-
sr_unix/mu_replpool_grab_sem.c | 60 +-
sr_unix/mu_replpool_release_sem.c | 14 +-
sr_unix/mu_rndwn_file.c | 31 +-
sr_unix/mu_rndwn_repl_instance.c | 14 +-
sr_unix/mu_rndwn_replpool.c | 124 +-
sr_unix/mu_rndwn_replpool.h | 12 +-
sr_unix/mu_size_arsample.c | 298 +-
sr_unix/mu_size_impsample.c | 207 +-
sr_unix/mu_size_scan.c | 119 +-
sr_unix/mubgetfil.c | 14 +-
sr_unix/mumps_clitab.c | 3 +-
sr_unix/mupip.c | 14 +-
sr_unix/mupip_cmd.c | 33 +-
sr_unix/mupip_cvtgbl.c | 44 +-
sr_unix/mupip_endiancvt.c | 4 +-
sr_unix/mupip_exit_handler.c | 6 +-
sr_unix/mupip_restore.c | 7 +-
sr_unix/mupip_rundown.c | 5 +-
sr_unix/mupip_size.c | 152 +-
sr_unix/mupip_size.h | 24 +-
sr_unix/mutex.c | 70 +-
sr_unix/obj_code.c | 9 +-
sr_unix/ojchildioclean.c | 14 +-
sr_unix/ojstartchild.c | 34 +-
sr_unix/op_fnfgncal.c | 4 +-
sr_unix/op_fnzpeek.c | 16 +-
sr_unix/op_fnzsearch.c | 19 +-
sr_unix/op_fnzsyslog.c | 47 +
sr_unix/op_job.c | 13 +-
sr_port/m_break.c => sr_unix/op_lab_ext.c | 30 +-
sr_unix/op_rhd_ext.c | 92 +
sr_unix/op_zedit.c | 4 +-
sr_unix/op_zlink.c | 155 +-
sr_unix/op_zmess.c | 64 +-
sr_unix/op_zrupdate.c | 161 +
sr_unix/open_object_file.c | 111 +
sr_unix/parse_file.c | 79 +-
sr_unix/parse_file.h | 66 +-
sr_unix/pinentry.m | 33 +-
sr_unix/reg_cmcheck.c | 15 +-
sr_unix/relinkctl.c | 468 +
sr_unix/relinkctl.h | 101 +
sr_unix/remove_rms.c | 8 +-
sr_unix/repl_instance.c | 4 +-
sr_unix/repl_sem.h | 4 +-
sr_unix/retain_list.txt | 0
sr_unix/rtnhdr.h | 77 +-
sr_unix/rts_error.c | 19 +-
sr_unix/runall.csh | 26 +-
sr_unix/secshr_client.c | 24 +-
sr_unix/send_msg.c | 4 +-
sr_unix/source_file.c | 8 +-
sr_unix/ss_initiate.c | 70 +-
sr_unix/std_dev_outbndset.c | 27 +-
sr_unix/term_setup.c | 8 +-
sr_unix/trigger_delete.c | 112 +-
sr_unix/trigger_delete_protos.h | 4 +-
sr_unix/trigger_parse.c | 17 +-
sr_unix/trigger_select.c | 10 +-
sr_unix/trigger_source_read_andor_verify.c | 4 +-
sr_unix/trigger_update.c | 153 +-
sr_unix/trigger_user_name.c | 27 +-
sr_unix/ttt.txt | 23 +-
sr_unix/urx_remove.c | 6 +-
sr_unix/util_exit_handler.c | 4 +-
sr_unix/util_help.c | 20 +-
sr_unix/util_output.c | 58 +-
sr_unix/wcs_flu.c | 21 +-
sr_unix/wcs_wtstart.c | 16 +-
sr_unix/zhist.c | 113 +
sr_unix/zhist.h | 42 +
sr_unix/zlmov_lnames.c | 26 +-
sr_unix/zro_load.c | 198 +-
sr_unix/zro_search.c | 61 +-
sr_unix/zroutinessp.h | 27 +-
sr_unix/zshow_devices.c | 22 +-
sr_unix_cm/gtcm_exit.c | 4 +-
sr_unix_cm/gtcm_init.c | 4 +-
sr_unix_cm/gtcm_loop.c | 4 +-
sr_unix_cm/gtcm_main.c | 12 +-
sr_unix_cm/gtcm_play.c | 16 +-
sr_unix_cm/gtcm_rep_err.c | 35 +-
sr_unix_cm/gtcm_shmclean.c | 3 +-
sr_unix_cm/omi_prc_conn.c | 76 +-
sr_unix_cm/omi_prc_qry.c | 15 +-
sr_unix_cm/rc_frmt_lck.c | 7 +-
sr_unix_gnp/gtcm_gnp_server.c | 32 +-
sr_unix_nsb/obj_code.c | 12 +-
sr_unix_nsb/opcode_def.h | 4 +-
sr_unix_nsb/resolve_ref.c | 12 +-
sr_unix_nsb/rtnhdr.h | 7 +-
sr_unix_nsb/ttt.txt | 11 +-
sr_vms_cm/gtcm_server.c | 10 +-
sr_vvms/bin_load.c | 7 +-
sr_vvms/ctrlc_set.c | 12 +-
sr_vvms/dse.c | 12 +-
sr_vvms/dse_cmd.cld | 11 +
sr_vvms/errorsp.h | 5 +-
sr_vvms/gtm$compile.c | 14 +-
sr_vvms/gtm$startup.c | 14 +-
sr_vvms/gtmsource_process_ops.c | 58 +-
sr_vvms/iott_use.c | 57 +-
sr_vvms/ious_iocontrol.c | 10 +-
sr_vvms/jnl_file_open.c | 7 +-
sr_vvms/lke.c | 14 +-
sr_vvms/mu_extract.c | 4 +-
sr_vvms/mubgetfil.c | 80 +-
sr_vvms/mupip.c | 12 +-
sr_vvms/op_fnzsearch.c | 20 +-
sr_vvms/op_zmess.c | 27 +-
sr_vvms/rtnhdr.h | 3 +-
sr_vvms/send_msg.c | 13 +-
sr_vvms/sgtm_putmsg.c | 13 +-
sr_vvms/spkitbld.m | 8 +-
sr_vvms/spkitupdate.com | 5 +-
sr_vvms/term_setup.c | 20 +-
sr_vvms/ttt.c | 1362 +-
sr_vvms/ttt.txt | 8 +-
sr_vvms/zshow_devices.c | 27 +-
sr_x86_64/auto_zlink_sp.c | 16 +-
sr_x86_64/auto_zlink_sp.h | 4 +-
sr_x86_64/cmerrors_ctl.c | 2 +-
sr_x86_64/cmierrors_ctl.c | 2 +-
sr_x86_64/gdeerrors_ctl.c | 2 +-
sr_x86_64/merrors_ansi.h | 49 +-
sr_x86_64/merrors_ctl.c | 114 +-
sr_x86_64/obj_filesp.c | 163 +-
sr_x86_64/op_extjmp.s | 6 +-
sr_x86_64/opp_setzbrk.s | 38 +
sr_x86_64/ttt.c | 1391 +-
598 files changed, 31428 insertions(+), 20962 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6512d64..9bb017b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2012, 2013 Fidelity Information Services, Inc #
+# Copyright 2012, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -26,7 +26,7 @@ foreach(lang ${languages})
endforeach()
# Defaults
-set(version V6.1-000)
+set(version V6.2-000)
if("${version}" STREQUAL "")
set(version V9.9-0)
endif()
@@ -36,8 +36,11 @@ if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
-# If it's a debug build make sure GT.M uses all of its debug options
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
+# Enable GT.M debug options unless directed not to enable them. Added to build without whitebox tests.
+set(GTM_ENABLE_DEBUG 1 CACHE BOOL "Enable GT.M debug options")
+if(GTM_ENABLE_DEBUG)
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
+endif()
set(install_permissions_script
OWNER_READ OWNER_EXECUTE OWNER_WRITE
@@ -57,9 +60,8 @@ set(gtm_osarch_libs "")
set(gt_src_list)
set(sources_used "")
set(extralibs "")
-# Disable encryption for the time being. Need to change this to invoke the gtmcrypt Makefile AS 2013.12.18
-set(is_encryption_supported 0)
-set(libmumpsrestoreregex "")
+set(GTMCRYPTLIB "GCRYPT")
+set(GTMCRYPTALGO "AES256CFB")
message("--> OS = ${CMAKE_SYSTEM_NAME} / ARCH = ${CMAKE_SYSTEM_PROCESSOR}")
# Establish platform
# Except for Solaris, CMAKE_COMPILER_IS_GNUCC is true
@@ -74,6 +76,7 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
else()
message(FATAL_ERROR "--> OS = ${CMAKE_SYSTEM_NAME} / ARCH = ${CMAKE_SYSTEM_PROCESSOR}")
endif()
+message("--> Encryption Library = ${GTMCRYPTLIB} / Algorithm = ${GTMCRYPTALGO}")
# Choose where to get bootstrap sources.
set(GTM_DIST "" CACHE PATH "Existing GT.M Distribution")
@@ -169,11 +172,6 @@ macro(set_source_list target)
set(src ${d}/${fname})
set("source_used_${fname}" 1)
list(APPEND sources_used ${source_dir_${d}}/${fname})
- if(NOT "${libmumpsrestoreregex}" STREQUAL "")
- if(";${name};" MATCHES ";(${libmumpsrestoreregex});")
- set("source_used_${fname}" 0)
- endif()
- endif()
break()
endif()
endforeach()
@@ -204,9 +202,6 @@ load_source_list(libgtcm sr_unix_cm/libgtcm.list)
load_source_list(liblke sr_unix/liblke.list)
load_source_list(libmupip sr_unix/libmupip.list)
load_source_list(libstub sr_unix/libstub.list)
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
- load_source_list(libgtmrpc sr_sun/libgtmrpc.list)
-endif()
# Assign sources to executables.
set_source_list(gtm_threadgbl_deftypes gtm_threadgbl_deftypes)
@@ -221,18 +216,14 @@ set_source_list(gtcm_server gtcm_main omi_srvc_xct)
set_source_list(gtcm_shmclean gtcm_shmclean)
set_source_list(gtmsecshr gtmsecshr_wrapper)
set_source_list(gtmsecshr_real gtmsecshr)
-set_source_list(libgtmcrypt gtmcrypt_ref gtmcrypt_pk_ref gtmcrypt_dbk_ref gtmcrypt_sym_ref)
-set_source_list(libgtmtls gtm_tls_impl)
-set_source_list(libgtmcryptutil gtmcrypt_util)
+set_source_list(libgtmcrypt gtmcrypt_ref gtmcrypt_pk_ref gtmcrypt_dbk_ref gtmcrypt_sym_ref gtmcrypt_util)
+set_source_list(libgtmtls gtm_tls_impl gtmcrypt_util)
set_source_list(libgtmshr gtm_main)
set_source_list(lke lke lke_cmd)
set_source_list(maskpass maskpass gtmcrypt_util)
set_source_list(mumps gtm)
set_source_list(mupip mupip mupip_cmd)
set_source_list(semstat2 semstat2)
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
- set_source_list(gtm_svc gtm_svc gtm_rpc_init gtm_dal_svc)
-endif()
#-----------------------------------------------------------------------------
# libmumps gets leftover sources, so compute the remaining list.
@@ -386,7 +377,7 @@ foreach(lib
endforeach()
# TODO: find_package or find_library for system libs?
-include_directories ("/usr/local/include")
+include_directories (/usr/local/include)
target_link_libraries(libmumps ${libmumpslibs})
add_executable(mumps ${mumps_SOURCES})
@@ -444,18 +435,6 @@ add_executable(semstat2 ${semstat2_SOURCES})
add_executable(ftok ${ftok_SOURCES})
target_link_libraries(ftok libmumps libstub)
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
- add_executable(gtm_svc ${gtm_svc_SOURCES})
- target_link_libraries(gtm_svc libmumps libgnpclient libcmisockettcp libgtmrpc)
-endif()
-foreach(t ${with_export})
- set_target_properties(${t} PROPERTIES
- LINK_FLAGS "${gtm_link}"
- LINK_DEPENDS "${gtm_dep}"
- )
- add_dependencies(${t} gen_export)
-endforeach()
-
add_library(libgtmshr MODULE ${libgtmshr_SOURCES})
set_property(TARGET libgtmshr PROPERTY OUTPUT_NAME gtmshr)
target_link_libraries(libgtmshr libmumps libgnpclient libcmisockettcp)
@@ -466,62 +445,51 @@ set_target_properties(libgtmshr PROPERTIES
add_dependencies(libgtmshr gen_export)
add_dependencies(mumps libgtmshr)
-if(is_encryption_supported)
- # Iterate over the list of GPG related libraries
- foreach(gpglib gpg-error gpgme gcrypt)
- # For each library, we need a new CMake variable, hence GPGLIB_${gpglib}
- find_library(GPGLIB_${gpglib} NAME ${gpglib} PATHS ${CMAKE_LIBRARY_PATH})
- # Append the found library to the list
- set(GPG_LIBRARIES ${GPG_LIBRARIES} ${GPGLIB_${gpglib}})
- endforeach()
-
- # Iterate over the list of SSL related libraries
- foreach(ssl)
- # For each library, we need a new CMake variable, hence TLSLIB_${tlslib}
- find_library(TLSLIB_${tlslib} NAME ${tlslib} PATHS ${CMAKE_LIBRARY_PATH})
- # Append the found library to the list
- set(TLS_LIBRARIES ${TLS_LIBRARIES} ${TLSLIB_${tlslib}})
- endforeach()
+# Iterate over the list of GPG related libraries
+foreach(gpglib gpg-error gpgme gcrypt config)
+ # For each library, we need a new CMake variable, hence GPGLIB_${gpglib}
+ find_library(GPGLIB_${gpglib} NAME ${gpglib} PATHS ${CMAKE_LIBRARY_PATH})
+ # Append the found library to the list
+ set(GPG_LIBRARIES ${GPG_LIBRARIES} ${GPGLIB_${gpglib}})
+endforeach()
- add_library(libgtmcrypt MODULE ${libgtmcrypt_SOURCES})
- set_target_properties(libgtmcrypt PROPERTIES
- OUTPUT_NAME gtmcrypt
- COMPILE_DEFINITIONS "USE_GCRYPT -DUSE_AES256CFB"
- LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
- )
- target_link_libraries(libgtmcrypt ${GPG_LIBRARIES})
- install(TARGETS libgtmcrypt DESTINATION ${GTM_INSTALL_DIR}/plugin)
+# Iterate over the list of SSL related libraries
+foreach(tlslib ssl crypto config)
+ # For each library, we need a new CMake variable, hence TLSLIB_${tlslib}
+ find_library(TLSLIB_${tlslib} NAME ${tlslib} PATHS ${CMAKE_LIBRARY_PATH})
+ # Append the found library to the list
+ set(TLS_LIBRARIES ${TLS_LIBRARIES} ${TLSLIB_${tlslib}})
+endforeach()
- add_library(libgtmtls MODULE ${libgtmtls_SOURCES})
- set_target_properties(libgtmtls PROPERTIES
- OUTPUT_NAME gtmtls
- LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
- )
- target_link_libraries(libgtmtls ${TLS_LIBRARIES})
- install(TARGETS libgtmtls DESTINATION ${GTM_INSTALL_DIR}/plugin)
-
- add_library(libgtmcryptutil MODULE ${libgtmcryptutil_SOURCES})
- set_target_properties(libgtmcryptutil PROPERTIES
- OUTPUT_NAME gtmcryptutil
- COMPILE_DEFINITIONS "USE_GCRYPT -DUSE_AES256CFB"
- LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
- )
- target_link_libraries(libgtmcryptutil ${GPG_LIBRARIES})
- install(TARGETS libgtmcryptutil DESTINATION ${GTM_INSTALL_DIR}/plugin)
-
- add_executable(maskpass ${maskpass_SOURCES})
- target_link_libraries(maskpass ${GPG_LIBRARIES})
- set_target_properties(maskpass PROPERTIES
- COMPILE_DEFINITIONS "USE_GCRYPT -DUSE_SYSLIB_FUNCS"
- RUNTIME_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin/gtmcrypt
- )
- install(TARGETS maskpass DESTINATION ${GTM_INSTALL_DIR}/plugin/gtmcrypt)
-endif()
+add_library(libgtmcrypt MODULE ${libgtmcrypt_SOURCES})
+set_target_properties(libgtmcrypt PROPERTIES
+ OUTPUT_NAME gtmcrypt
+ COMPILE_DEFINITIONS "USE_${GTMCRYPTLIB} -DUSE_${GTMCRYPTALGO}"
+ LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
+ )
+target_link_libraries(libgtmcrypt ${GPG_LIBRARIES})
+install(TARGETS libgtmcrypt DESTINATION ${GTM_INSTALL_DIR}/plugin)
+
+add_library(libgtmtls MODULE ${libgtmtls_SOURCES})
+set_target_properties(libgtmtls PROPERTIES
+ OUTPUT_NAME gtmtls
+ COMPILE_DEFINITIONS "USE_OPENSSL"
+ LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
+ )
+target_link_libraries(libgtmtls ${TLS_LIBRARIES})
+install(TARGETS libgtmtls DESTINATION ${GTM_INSTALL_DIR}/plugin)
+
+add_executable(maskpass ${maskpass_SOURCES})
+target_link_libraries(maskpass ${GPG_LIBRARIES} ${TLS_LIBRARIES})
+set_target_properties(maskpass PROPERTIES
+ COMPILE_DEFINITIONS "USE_${GTMCRYPTLIB} -DUSE_SYSLIB_FUNCS"
+ RUNTIME_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin/gtmcrypt
+ )
+install(TARGETS maskpass DESTINATION ${GTM_INSTALL_DIR}/plugin/gtmcrypt)
# Always copy files into the plugin directory
foreach(f
Makefile.mk
- add_db_key.sh
encrypt_sign_db_key.sh
gen_keypair.sh
gen_sym_hash.sh
diff --git a/LICENSE b/LICENSE
index 9adedf4..4c843de 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-All software in this package is part of FIS GT.M (http://fis-gtm.com) which is Copyright 2013 Fidelity Information
+All software in this package is part of FIS GT.M (http://fis-gtm.com) which is Copyright 2014 Fidelity Information
Services, Inc., and provided to you under the terms of a license. If there is a COPYING file included in this package,
it contains the terms of the license under which the package is provided to you. If there is not a COPYING file in the
package, you must ensure that your use of FIS GT.M complies with the license under which it is provided. If you are
diff --git a/README b/README
index 5fdb02d..43fd188 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
All software in this package is part of FIS GT.M (http://fis-gtm.com)
-which is Copyright 2013 Fidelity Information Services, Inc., and
+which is Copyright 2014 Fidelity Information Services, Inc., and
provided to you under the terms of a license. If there is a COPYING
file included in this package, it contains the terms of the license under
which the package is provided to you. If there is not a COPYING file in
@@ -31,11 +31,11 @@ To build GT.M for Linux, do the following steps:
from http://sourceforge.net/projects/fis-gtm/ Unpack the tar file and run
the configure script as root. Note: the tar file unpacks everything into
your current working directory, not a new subdirectory. The Linux Standard
- Base (LSB) install path for GT.M V6.1-000 is /opt/fis-gtm/V6.1-000_i686 or
- /opt/fis-gtm/V6.1-000_x8664. These instrcutions are written using x8664, please
- use i686 as necessary.
+ Base (LSB) install path for GT.M V6.2-000 is /opt/fis-gtm/V6.2-000_i586 or
+ /opt/fis-gtm/V6.2-000_x8664. These instructions are written using x8664, please
+ use i586 as necessary.
- $ tar xfz gtm_V61000_linux_x8664_pro.tar.gz
+ $ tar xfz gtm_V62000_linux_x8664_pro.tar.gz
# Note down the installation path for use with cmake below
@@ -43,16 +43,16 @@ To build GT.M for Linux, do the following steps:
2. Unpack the GT.M sources
The GT.M source tarball extracts to a directory with the version number in
- the name, fis-gtm-V6.1-000
- $ tar xfz fis-gtm-V6.1-000.tar.gz
- $ cd fis-gtm-V6.1-000
+ the name, fis-gtm-V6.2-000
+ $ tar xfz fis-gtm-V6.2-000.tar.gz
+ $ cd fis-gtm-V6.2-000
You should find this README, LICENSE, COPYING and CMakeLists.txt file and
sr_* source directories.
3. Building GT.M -
<fis-gtm-build> can be a sub directory of the source directory,
- fis-gtm-V6.1-000, or any other valid path.
+ fis-gtm-V6.2-000, or any other valid path.
$ mkdir <fis-gtm-build>
$ cd <fis-gtm-build>
@@ -71,16 +71,16 @@ To build GT.M for Linux, do the following steps:
#
# -D CMAKE_INSTALL_PREFIX:PATH=${PWD}/package
#
- $ cmake <path to>/fis-gtm-V6.1-000 -D CMAKE_INSTALL_PREFIX:PATH=${PWD}/package
+ $ cmake -D CMAKE_INSTALL_PREFIX:PATH=${PWD}/package <path to>/fis-gtm-V6.2-000
$ make
$ make install
- $ cd package/lib/fis-gtm/V6.1-000_x86_64
+ $ cd package/lib/fis-gtm/V6.2-000_x86_64
# Now you are ready to install GT.M. Answer a few questions and install it.
- # The recommended installation path is /opt/fis-gtm/V6.1-000_x86_64
+ # The recommended installation path is /opt/fis-gtm/V6.2-000_x86_64
$ sudo ./configure
diff --git a/sr_avms/fetch_all.m64 b/sr_avms/fetch_all.m64
new file mode 100644
index 0000000..183ec2a
--- /dev/null
+++ b/sr_avms/fetch_all.m64
@@ -0,0 +1,41 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; ;
+; Copyright 2014 Fidelity Information Services, Inc ;
+; ;
+; This source code contains the intellectual property ;
+; of its copyright holder(s), and is made available ;
+; under a license. If you do not know the terms of ;
+; the license, please stop and do not read further. ;
+; ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; this calls gtm_fetch with a count of zero arguments - something varargs processing in VMS can't do without help
+; this form of call to gtm_fetch binds all existing local variables instead of a passed list
+ .title FETCH_ALL
+
+ G_MSF
+
+ $linkage_section
+
+a_fetch_all:
+ .linkage_pair fetch_all
+
+ $code_section
+
+
+;*1*********************************************************************
+ $routine FETCH_ALL, entry=FETCH_ALL_CA, kind=null
+
+ lda sp, -8(sp)
+ stq r26, (sp)
+ .base r27, $ls
+ mov 0, r25 ; argument count
+ mov 0, r28 ; argument count on the stack
+ $call gtm_fetch, set_arg_info=false, nonstandard=true
+ ldq r26, (sp)
+ lda sp, 8(sp)
+ ret r26
+
+ $end_routine
+
+ .end
+
diff --git a/sr_avms/op_extjmp.m64 b/sr_avms/op_extjmp.m64
index 3792f2a..9ef8689 100644
--- a/sr_avms/op_extjmp.m64
+++ b/sr_avms/op_extjmp.m64
@@ -1,7 +1,7 @@
.title op_extjmp - jump to a label in an external (MUMPS) routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2005, 2012 Fidelity Information Services, Inc ;
+; Copyright 2005, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -29,7 +29,7 @@
A_frame_pointer: .address frame_pointer
L_ERR_GTMCHECK: .long ERR_GTMCHECK
-L_ERR_LABELUNKNOWN: .long ERR_LABELUNKNOWN
+L_ERR_LABELNOTFND: .long ERR_LABELNOTFND
$data_section
@@ -100,7 +100,7 @@ L30: $call lib$signal, args=<L_ERR_GTMCHECK/L>
ret r26
$end_epilogue
-L40: $call lib$signal, args=<L_ERR_LABELUNKNOWN/L>
+L40: $call lib$signal, args=<L_ERR_LABELNOTFND/L>
$begin_epilogue
getframe
imb
diff --git a/sr_avms/release_name.h b/sr_avms/release_name.h
index 150f221..632b116 100644
--- a/sr_avms/release_name.h
+++ b/sr_avms/release_name.h
@@ -9,6 +9,6 @@
* *
****************************************************************/
-#define GTM_RELEASE_NAME "GT.M V6.1-000 VMS AXP"
+#define GTM_RELEASE_NAME "GT.M V6.2-000 VMS AXP"
#define GTM_PRODUCT "GT.M"
-#define GTM_VERSION "V6.1"
+#define GTM_VERSION "V6.2"
diff --git a/sr_i386/cmerrors_ctl.c b/sr_i386/cmerrors_ctl.c
index 0d89e8f..02581fe 100644
--- a/sr_i386/cmerrors_ctl.c
+++ b/sr_i386/cmerrors_ctl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
diff --git a/sr_i386/cmierrors_ctl.c b/sr_i386/cmierrors_ctl.c
index d8493c8..3656c97 100644
--- a/sr_i386/cmierrors_ctl.c
+++ b/sr_i386/cmierrors_ctl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
diff --git a/sr_i386/error.si b/sr_i386/error.si
index 0325ac4..3a47b7b 100644
--- a/sr_i386/error.si
+++ b/sr_i386/error.si
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2012 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -16,14 +16,14 @@
#-----------------------------------------------
.ifdef cygwin
# will need another 8 to save sigmasks
-chnd_size = 220
+chnd_size = 224
.else
-chnd_size = 168
+chnd_size = 172
.endif
chnd_save_active = 0
chnd_ch_active = 4
-chnd_ch = 8
-chnd_jmp = 12
+chnd_ch = 12
+chnd_jmp = 16
.data
.extern ctxt
diff --git a/sr_i386/gdeerrors_ctl.c b/sr_i386/gdeerrors_ctl.c
index 07cc7be..d43120c 100644
--- a/sr_i386/gdeerrors_ctl.c
+++ b/sr_i386/gdeerrors_ctl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
diff --git a/sr_i386/incr_link.c b/sr_i386/incr_link.c
index 5ad8c02..10b9738 100644
--- a/sr_i386/incr_link.c
+++ b/sr_i386/incr_link.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -36,7 +36,7 @@ static char *code;
GBLREF mident_fixed zlink_mname;
GBLREF boolean_t gtm_utf8_mode;
-error_def(ERR_INVOBJ);
+error_def(ERR_INVOBJFILE);
error_def(ERR_LOADRUNNING);
error_def(ERR_TEXT);
@@ -49,9 +49,9 @@ typedef struct res_list_struct
void res_free(res_list *root);
bool addr_fix(int file, struct exec *fhead, urx_rtnref *urx_lcl, rhdtyp *code);
-void zl_error(int4 file, int4 err, int4 err2, int4 len, char *addr);
+void zl_error(int4 file, int4 err, int4 len, char *addr, int4 err2, int4 len2, char *addr2);
-bool incr_link(int file_desc)
+boolean_t incr_link(int file_desc, zro_ent *dummy, uint4 fname_len, char *fname)
{
rhdtyp *hdr, *old_rhead;
int code_size, save_errno, cnt;
@@ -64,6 +64,7 @@ bool incr_link(int file_desc)
int order;
struct exec file_hdr;
+ assert(file_desc);
urx_lcl_anchor.len = 0;
urx_lcl_anchor.addr = 0;
urx_lcl_anchor.lab = 0;
@@ -75,14 +76,14 @@ bool incr_link(int file_desc)
if (-1 == read_size)
{
save_errno = errno;
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT, strlen(STRERROR(save_errno)),
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT, strlen(STRERROR(save_errno)),
STRERROR(save_errno));
} else
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT, RTS_ERROR_TEXT("reading file header"));
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT, RTS_ERROR_TEXT("reading file header"));
} else if (OMAGIC != file_hdr.a_magic)
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT, RTS_ERROR_TEXT("bad magic"));
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT, RTS_ERROR_TEXT("bad magic"));
else if (OBJ_LABEL != file_hdr.a_stamp)
- return FALSE; /* wrong version */
+ return IL_RECOMPILE; /* wrong version */
assert(0 == file_hdr.a_bss);
code_size = file_hdr.a_text + file_hdr.a_data;
code = GTM_TEXT_ALLOC(code_size);
@@ -92,20 +93,22 @@ bool incr_link(int file_desc)
if (-1 == read_size)
{
save_errno = errno;
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT, strlen(STRERROR(save_errno)), STRERROR(save_errno)); /* BYPASSOK */
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT, strlen(STRERROR(save_errno)),
+ STRERROR(save_errno));
} else
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT, RTS_ERROR_TEXT("reading code"));
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT, RTS_ERROR_TEXT("reading code"));
}
hdr = (rhdtyp *)code;
if (memcmp(&hdr->jsb[0], "GTM_CODE", SIZEOF(hdr->jsb)))
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT, RTS_ERROR_TEXT("missing GTM_CODE"));
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT, RTS_ERROR_TEXT("missing GTM_CODE"));
if ((hdr->compiler_qlf & CQ_UTF8) && !gtm_utf8_mode)
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT,
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT,
RTS_ERROR_TEXT("Object compiled with CHSET=UTF-8 which is different from $ZCHSET"));
if (!(hdr->compiler_qlf & CQ_UTF8) && gtm_utf8_mode)
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT,
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT,
RTS_ERROR_TEXT("Object compiled with CHSET=M which is different from $ZCHSET"));
literal_ptr = code + file_hdr.a_text;
+ hdr->routine_source_offset += (uint4)literal_ptr; /* now an absolute pointer, not an offset */
for (cnt = hdr->vartab_len, curvar = VARTAB_ADR(hdr); cnt; --cnt, ++curvar)
{ /* relocate the variable table */
assert(0 < curvar->var_name.len);
@@ -117,14 +120,14 @@ bool incr_link(int file_desc)
if (!addr_fix(file_desc, &file_hdr, &urx_lcl_anchor, hdr))
{
urx_free(&urx_lcl_anchor);
- zl_error(file_desc, ERR_INVOBJ, ERR_TEXT, RTS_ERROR_TEXT("address fixup failure"));
+ zl_error(file_desc, ERR_INVOBJFILE, fname_len, fname, ERR_TEXT, RTS_ERROR_TEXT("address fixup failure"));
}
if (!zlput_rname(hdr))
{
urx_free(&urx_lcl_anchor);
/* Copy routine name to local variable because zl_error free's it. */
memcpy(&module_name[0], hdr->routine_name.addr, hdr->routine_name.len);
- zl_error(file_desc, 0, ERR_LOADRUNNING, hdr->routine_name.len, &module_name[0]);
+ zl_error(file_desc, ERR_LOADRUNNING, hdr->routine_name.len, &module_name[0], 0, 0, NULL);
}
urx_add(&urx_lcl_anchor);
old_rhead = (rhdtyp *)hdr->old_rhead_ptr;
@@ -162,7 +165,7 @@ bool incr_link(int file_desc)
old_rhead = (rhdtyp *) old_rhead->old_rhead_ptr;
}
urx_resolve(hdr, lbt_bot, lbt_top);
- return TRUE;
+ return IL_DONE;
}
bool addr_fix(int file, struct exec *fhead, urx_rtnref *urx_lcl, rhdtyp *code)
@@ -406,7 +409,7 @@ void res_free(res_list *root)
* err - an error code that accepts no arguments and
* err2 - an error code that accepts two arguments (!AD)
*/
-void zl_error(int4 file, int4 err, int4 err2, int4 len, char *addr)
+void zl_error(int4 file, int4 err, int4 len, char *addr, int4 err2, int4 len2, char *addr2)
{
int rc;
@@ -416,13 +419,8 @@ void zl_error(int4 file, int4 err, int4 err2, int4 len, char *addr)
code = NULL;
}
CLOSEFILE_RESET(file, rc); /* resets "file" to FD_INVALID */
- if ((0 != err) && (0 != err2))
- rts_error(VARLSTCNT(6) err, 0, err2, 2, len, addr);
- else if (0 != err)
- rts_error(VARLSTCNT(1) err);
+ if (0 != err2)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) err, 2, len, addr, err2, 2, len2, addr2);
else
- {
- assert(0 != err2);
- rts_error(VARLSTCNT(4) err2, 2, len, addr);
- }
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) err, 2, len, addr);
}
diff --git a/sr_i386/merrors_ansi.h b/sr_i386/merrors_ansi.h
index 0df7c77..20e9320 100644
--- a/sr_i386/merrors_ansi.h
+++ b/sr_i386/merrors_ansi.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -93,7 +93,7 @@ const static readonly int error_ansi[] = {
7, /* GVUNDEF */
0, /* TRANSNEST */
0, /* INDEXTRACHARS */
- 0, /* UNUSEDMSG260 */
+ 0, /* CORRUPTNODE */
0, /* INDRMAXLEN */
0, /* INSFFBCNT */
0, /* INTEGERRS */
@@ -642,7 +642,7 @@ const static readonly int error_ansi[] = {
0, /* JNLRDONLY */
0, /* ANCOMPTINC */
0, /* ABNCOMPTINC */
- 0, /* UNUSEDMSG809 */
+ 0, /* RECLOAD */
0, /* SOCKNOTFND */
0, /* CURRSOCKOFR */
79, /* SOCKETEXIST */
@@ -822,16 +822,16 @@ const static readonly int error_ansi[] = {
0, /* RENAMEFAIL */
0, /* FILERENAME */
0, /* JNLBUFINFO */
- 0, /* UNUSEDMSG989 */
- 0, /* UNUSEDMSG990 */
+ 0, /* SDSEEKERR */
+ 0, /* LOCALSOCKREQ */
0, /* TPNOTACID */
0, /* JNLSETDATA2LONG */
0, /* JNLNEWREC */
0, /* REPLFTOKSEM */
- 0, /* UNUSEDMSG995 */
+ 0, /* SOCKNOTPASSED */
0, /* EXTRIOERR */
0, /* EXTRCLOSEERR */
- 0, /* UNUSEDMSG998 */
+ 0, /* CONNSOCKREQ */
0, /* REPLEXITERR */
0, /* MUDESTROYSUC */
0, /* DBRNDWN */
@@ -912,7 +912,7 @@ const static readonly int error_ansi[] = {
0, /* SYSTEMVALUE */
0, /* SIZENOTVALID4 */
0, /* STRNOTVALID */
- 0, /* UNUSEDMSG1079 */
+ 0, /* CREDNOTPASSED */
0, /* ERRWETRAP */
0, /* TRACINGON */
0, /* CITABENV */
@@ -942,7 +942,7 @@ const static readonly int error_ansi[] = {
0, /* MAXBTLEVEL */
35, /* INVMNEMCSPC */
0, /* JNLALIGNSZCHG */
- 0, /* UNUSEDMSG1109 */
+ 0, /* SEFCTNEEDSFULLB */
0, /* GVFAILCORE */
0, /* DBCDBNOCERTIFY */
0, /* DBFRZRESETSUC */
@@ -1089,7 +1089,7 @@ const static readonly int error_ansi[] = {
0, /* REPLINSTSTNDALN */
0, /* REPLREQROLLBACK */
0, /* REQROLLBACK */
- 0, /* UNUSEDMSG1256 */
+ 0, /* INVOBJFILE */
0, /* SRCSRVEXISTS */
0, /* SRCSRVNOTEXIST */
0, /* SRCSRVTOOMANY */
@@ -1250,7 +1250,7 @@ const static readonly int error_ansi[] = {
0, /* MUUSERECOV */
0, /* SECNOTSUPPLEMENTARY */
0, /* SUPRCVRNEEDSSUPSRC */
- 0, /* UNUSEDMSG1417 */
+ 0, /* PEERPIDMISMATCH */
0, /* SETITIMERFAILED */
0, /* UPDSYNC2MTINS */
0, /* UPDSYNCINSTFILE */
@@ -1380,4 +1380,31 @@ const static readonly int error_ansi[] = {
0, /* TLSIOERROR */
0, /* TLSRENEGOTIATE */
0, /* REPLNOTLS */
+ 0, /* COLTRANSSTR2LONG */
+ 0, /* SOCKPASS */
+ 0, /* SOCKACCEPT */
+ 0, /* NOSOCKHANDLE */
+ 0, /* TRIGLOADFAIL */
+ 0, /* SOCKPASSDATAMIX */
+ 0, /* NOGTCMDB */
+ 0, /* NOUSERDB */
+ 0, /* DSENOTOPEN */
+ 0, /* ZSOCKETATTR */
+ 0, /* ZSOCKETNOTSOCK */
+ 0, /* CHSETALREADY */
+ 0, /* DSEMAXBLKSAV */
+ 0, /* BLKINVALID */
+ 0, /* CANTBITMAP */
+ 0, /* AIMGBLKFAIL */
+ 0, /* GTMDISTUNVERIF */
+ 0, /* CRYPTNOAPPEND */
+ 0, /* CRYPTNOSEEK */
+ 0, /* CRYPTNOTRUNC */
+ 0, /* CRYPTNOKEYSPEC */
+ 0, /* CRYPTNOOVERRIDE */
+ 0, /* CRYPTKEYTOOBIG */
+ 0, /* CRYPTBADWRTPOS */
+ 13, /* LABELNOTFND */
+ 0, /* RELINKCTLERR */
+ 0, /* INVLINKTMPDIR */
};
diff --git a/sr_i386/merrors_ctl.c b/sr_i386/merrors_ctl.c
index c8412e9..4c4ea08 100644
--- a/sr_i386/merrors_ctl.c
+++ b/sr_i386/merrors_ctl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,8 +42,8 @@ LITDEF err_msg merrors[] = {
"DBRDERR", "Cannot read database file !AD after opening", 2,
"CCEDUMPNOW", "", 0,
"DEVPARINAP", "Device parameter inappropriate to this command", 0,
- "RECORDSTAT", "!AD:!_ Key cnt: !UL max subsc len: !UL max rec len: !UL max node len: !UL", 6,
- "NOTGBL", "!_!AD!/!_!_!_\"^\" Expected", 2,
+ "RECORDSTAT", "!AD:!_ Key cnt: !@ZQ max subsc len: !UL max rec len: !UL max node len: !UL", 6,
+ "NOTGBL", "Expected a global variable name starting with an up-arrow (^): !AD", 2,
"DEVPARPROT", "The protection specification is invalid", 0,
"PREMATEOF", "Premature end of file detected", 0,
"GVINVALID", "!_!AD!/!_!_!_Invalid global name", 2,
@@ -95,7 +95,7 @@ LITDEF err_msg merrors[] = {
"GVUNDEF", "Global variable undefined: !AD", 2,
"TRANSNEST", "Maximum transaction nesting levels exceeded", 0,
"INDEXTRACHARS", "Indirection string contains extra trailing characters", 0,
- "UNUSEDMSG260", "INDMAXNEST Last used in V6.0-000", 0,
+ "CORRUPTNODE", "Corrupt input in Record # !UL, Key #!UL; resuming with next global node", 2,
"INDRMAXLEN", "Maximum length !UL of an indirection argument was exceeded", 1,
"INSFFBCNT", "Insufficient byte count quota left for requested operation", 0,
"INTEGERRS", "Database integrity errors", 0,
@@ -644,7 +644,7 @@ LITDEF err_msg merrors[] = {
"JNLRDONLY", "Journal file !AD read only", 2,
"ANCOMPTINC", "Deviceparameter !AD is not compatible with any other deviceparameters in the !AD command", 4,
"ABNCOMPTINC", "Deviceparameter !AD and deviceparameter !AD are not compatible in the !AD command", 6,
- "UNUSEDMSG809", "GTMSECSHRLOGF last used in V5.5-000", 0,
+ "RECLOAD", "Error loading record number: !UL!/", 1,
"SOCKNOTFND", "Socket !AD not found", 2,
"CURRSOCKOFR", "Current socket of index !UL is out of range. There are only !UL sockets.", 2,
"SOCKETEXIST", "Socket !AD already exists", 2,
@@ -824,16 +824,16 @@ LITDEF err_msg merrors[] = {
"RENAMEFAIL", "Rename of file !AD to !AD failed", 4,
"FILERENAME", "File !AD is renamed to !AD", 4,
"JNLBUFINFO", "Pid 0x!XL!/ dsk 0x!XL free 0x!XL bytcnt 0x!XL io_in_prog 0x!XL fsync_in_prog 0x!XL!/ dskaddr 0x!XL freeaddr 0x!XL qiocnt 0x!XL now_writer 0x!XL fsync_pid 0x!XL!/filesize 0x!XL cycle 0x!XL errcnt 0x!XL wrtsize 0x!XL fsync_dskaddr 0x!XL", 16,
- "UNUSEDMSG989", "JNLQIOLOCKED : Last used in V4.4-000", 0,
- "UNUSEDMSG990", "JNLEOFPREZERO : Last used in V4.4-000", 0,
+ "SDSEEKERR", "Sequential device seek error - !AD", 2,
+ "LOCALSOCKREQ", "LOCAL socket required", 0,
"TPNOTACID", "!AD at !AD in a final TP retry violates ACID properties of a TRANSACTION; indefinite RESTARTs may occur !AD !AD", 8,
"JNLSETDATA2LONG", "SET journal record has data of length !UL. Target system cannot handle data more than !UL bytes.", 2,
"JNLNEWREC", "Target system cannot recognize journal record of type !UL, last recognized type is !UL", 2,
"REPLFTOKSEM", "Error with replication semaphores for instance file !AD", 2,
- "UNUSEDMSG995", "GETCWD : Last used before V4.0-001E", 0,
+ "SOCKNOTPASSED", "Socket message contained no passed socket descriptors", 0,
"EXTRIOERR", "Error writing extract file !AD", 2,
"EXTRCLOSEERR", "Error closing extract file !AD", 2,
- "UNUSEDMSG998", "TRUNCATE : Last used in V4.3-001F", 0,
+ "CONNSOCKREQ", "Socket not connected", 0,
"REPLEXITERR", "Replication process encountered an error while exiting", 0,
"MUDESTROYSUC", "Global section (!AD) corresponding to file !AD successfully destroyed", 4,
"DBRNDWN", "Error during global database rundown for region !AD.!/Notify those responsible for proper database operation.", 2,
@@ -872,7 +872,7 @@ LITDEF err_msg merrors[] = {
"NOCHLEFT", "Unhandled condition exception (all handlers exhausted) - process terminating", 0,
"MULOGNAMEDEF", "Logical name !AD, needed to start replication server is already defined for this job. !/Check for an existing or improperly terminated server.", 2,
"BUFOWNERSTUCK", "Pid !UL waiting for Pid !UL to finish disk-read of block !UL [0x!XL].!/Been waiting for !UL minutes. read_in_progress=!UL : rip_latch = !UL.", 7,
- "ACTIVATEFAIL", "Failed to activate passive source server for secondary instance !AD", 2,
+ "ACTIVATEFAIL", "Cannot activate passive source server on instance !AD while a receiver server and/or update process is running", 2,
"DBRNDWNWRN", "Global section of database file !AD not rundown successfully by pid !UL [0x!XL]. Global section was not removed.", 4,
"DLLNOOPEN", "Failed to load external dynamic library !AD", 2,
"DLLNORTN", "Failed to look up the location of the symbol !AD", 2,
@@ -914,7 +914,7 @@ LITDEF err_msg merrors[] = {
"SYSTEMVALUE", "Invalid value for $SYSTEM (!AD)", 2,
"SIZENOTVALID4", "Size (in bytes) must be either 1, 2, or 4", 0,
"STRNOTVALID", "Error: cannot convert !AD value to valid value", 2,
- "UNUSEDMSG1079", "RECNOCREJNL : Last used in V4.3-001F", 0,
+ "CREDNOTPASSED", "Socket message contained no passed credentials", 0,
"ERRWETRAP", "Error while processing $ETRAP", 0,
"TRACINGON", "Tracing already turned on", 0,
"CITABENV", "Environment variable for call-in table !AD not set", 2,
@@ -941,10 +941,10 @@ LITDEF err_msg merrors[] = {
"INVZDIRFORM", "Invalid value (!UL) specified for ZDIR_FORM", 1,
"ZDIROUTOFSYNC", "$ZDIRECTORY !AD is not the same as its cached value !AD", 4,
"GBLNOEXIST", "Global !AD no longer exists", 2,
- "MAXBTLEVEL", "Global !AD reached maximum level", 2,
+ "MAXBTLEVEL", "Global ^!AD in region !AD reached maximum level", 4,
"INVMNEMCSPC", "Unsupported mnemonicspace !AD", 2,
"JNLALIGNSZCHG", "Journal ALIGNSIZE is rounded up to !UL blocks (closest next higher power of two)", 1,
- "UNUSEDMSG1109", "MAXTRACELEVEL : last used in V5.4-002B", 0,
+ "SEFCTNEEDSFULLB", "Current side effect setting does not permit full Boolean to be turned off", 0,
"GVFAILCORE", "A core file is being created for later analysis if necessary", 0,
"DBCDBNOCERTIFY", "Database !AD HAS NOT been certified due to the preceding errors - rerun DBCERTIFY SCAN", 2,
"DBFRZRESETSUC", "Freeze released successfully on database file !AD", 2,
@@ -1091,7 +1091,7 @@ LITDEF err_msg merrors[] = {
"REPLINSTSTNDALN", "Could not get exclusive access to replication instance file !AD", 2,
"REPLREQROLLBACK", "Replication instance file !AD indicates abnormal shutdown or an incomplete ROLLBACK. Run MUPIP JOURNAL ROLLBACK first", 2,
"REQROLLBACK", "Error accessing database !AD. Run MUPIP JOURNAL ROLLBACK on cluster node !AD.", 4,
- "UNUSEDMSG1256", "REPLUPGRADESEC : Last used in V5.4-002B", 0,
+ "INVOBJFILE", "Cannot ZLINK object file !AD due to unexpected format", 2,
"SRCSRVEXISTS", "Source server for secondary instance !AD is already running with pid !UL", 3,
"SRCSRVNOTEXIST", "Source server for secondary instance !AD is not alive", 2,
"SRCSRVTOOMANY", "Cannot start more than !UL source servers in replication instance !AD", 3,
@@ -1131,7 +1131,7 @@ LITDEF err_msg merrors[] = {
"COMMITWAITSTUCK", "Pid !UL timed out after waiting !UL minute(s) for !UL concurrent GT.M process(es) to finish commits in database file !AD", 5,
"COMMITWAITPID", "Pid !UL waited !UL minute(s) for pid !UL to finish commits to block 0x!XL in database file !AD", 6,
"UPDREPLSTATEOFF", "Error replicating global ^!AD as it maps to database !AD which has replication turned OFF", 4,
- "LITNONGRAPH", "M standard requires graphics in string literals", 0,
+ "LITNONGRAPH", "M standard requires graphics in string literals; found non-printable: $ZCHAR(!AD)", 2,
"DBFHEADERR8", "Database file !AD: control problem: !AD was 0x!16 at XQ expecting 0x!16 at XQ", 6,
"MMBEFOREJNL", "BEFORE image journaling cannot be set with MM access method in database file !AD", 2,
"MMNOBFORRPL", "Replication cannot be used in database file !AD which uses MM access method and NOBEFORE image journaling", 2,
@@ -1252,7 +1252,7 @@ LITDEF err_msg merrors[] = {
"MUUSERECOV", "Abnormal shutdown of journaled database !AD detected", 2,
"SECNOTSUPPLEMENTARY", "!AD is a Supplementary Instance and so cannot act as a source to non-Supplementary Instance !AD ", 4,
"SUPRCVRNEEDSSUPSRC", "Instance !AD is not configured to perform local updates so it cannot act as a receiver for non-Supplementary Instance !AD", 4,
- "UNUSEDMSG1417", "SYNCTOSAMETYPE: Never used before so slot free for reuse", 0,
+ "PEERPIDMISMATCH", "Local socket peer with PID=!UL does not match specified PID=!UL", 2,
"SETITIMERFAILED", "A setitimer() call returned an error status of !UL", 1,
"UPDSYNC2MTINS", "Can only UPDATERESYNC with an empty instance file", 0,
"UPDSYNCINSTFILE", "Error with instance file name specified in UPDATERESYNC qualifier", 0,
@@ -1322,7 +1322,7 @@ LITDEF err_msg merrors[] = {
"JNLBUFFDBUPD", "Journal file buffer size for database file !AD has been adjusted from !UL to !UL.", 4,
"LOCKINCR2HIGH", "Attempt to increment a LOCK more than !UL times", 1,
"LOCKIS", "!_!_Resource name: !AD", 2,
- "LDSPANGLOINCMP", "Incomplete spanning node found during load", 0,
+ "LDSPANGLOINCMP", "Incomplete spanning node found during load!/!_!_at File offset : [0x!16 at XQ]", 1,
"MUFILRNDWNFL2", "Database section (id = !UL) belonging to database file !AD rundown failed", 3,
"MUINSTFROZEN", "!AD : Instance !AZ is frozen. Waiting for instance to be unfrozen before proceeding with writes to database file !AD", 5,
"MUINSTUNFROZEN", "!AD : Instance !AZ is now Unfrozen. Continuing with writes to database file !AD", 5,
@@ -1363,7 +1363,7 @@ LITDEF err_msg merrors[] = {
"INSTFRZDEFER", "Instance Freeze initiated by !AD error on region !AD deferred due to critical resource conflict", 4,
"REGOPENRETRY", "Attempt to open region !AD (!AD) using startup shortcut failed due to conflicting database shutdown. Retrying...", 4,
"REGOPENFAIL", "Failed to open region !AD (!AD) due to conflicting database shutdown activity", 4,
- "REPLINSTNOSHM", "Database !AD has no active connection to a replication journal pool; please verify that the database is listed in your instance file", 2,
+ "REPLINSTNOSHM", "Database !AD has no active connection to a replication journal pool", 2,
"DEVPARMTOOSMALL", "Deviceparameter must be greater than zero (0)", 0,
"REMOTEDBNOSPGBL", "Database region !AD contains portion of a spanning global and so cannot point to a remote file", 2,
"NCTCOLLSPGBL", "Database region !AD contains portion of spanning global ^!AD and so cannot support non-zero numeric collation type", 4,
@@ -1382,6 +1382,33 @@ LITDEF err_msg merrors[] = {
"TLSIOERROR", "Error during TLS/SSL !AD operation", 2,
"TLSRENEGOTIATE", "Failed to renegotiate TLS/SSL connection", 0,
"REPLNOTLS", "!AD requested TLS/SSL communication but the !AD was either not started with TLSID qualifier or does not support TLS/SSL protocol", 4,
+ "COLTRANSSTR2LONG", "Output string after collation transformation is too long", 0,
+ "SOCKPASS", "Socket pass failed", 0,
+ "SOCKACCEPT", "Socket accept failed", 0,
+ "NOSOCKHANDLE", "No socket handle specified in WRITE /PASS", 0,
+ "TRIGLOADFAIL", "MUPIP TRIGGER or $ZTRIGGER operation failed. Failure code: !AD.", 2,
+ "SOCKPASSDATAMIX", "Attempt to use a LOCAL socket for both READ/WRITE and PASS/ACCEPT", 0,
+ "NOGTCMDB", "!AD does not support operation on GT.CM database region: !AD", 4,
+ "NOUSERDB", "!AD does not support operation on non-GDS format region: !AD", 4,
+ "DSENOTOPEN", "DSE could not open region !AD - see DSE startup error message for cause", 2,
+ "ZSOCKETATTR", "Attribute \"!AD\" invalid for $ZSOCKET function", 2,
+ "ZSOCKETNOTSOCK", "$ZSOCKET function called but device is not a socket", 0,
+ "CHSETALREADY", "CHSET !AD already specified for socket device", 2,
+ "DSEMAXBLKSAV", "DSE cannot SAVE another block as it already has the maximum of !UL", 1,
+ "BLKINVALID", "!XL is not a valid block as database file !AD has !XL total blocks", 4,
+ "CANTBITMAP", "Can't perform this operation on a bit map (block at a 200 hexadecimal boundary)", 0,
+ "AIMGBLKFAIL", "After image build for block !XL in region !AD failed in DSE or MUPIP", 3,
+ "GTMDISTUNVERIF", "Environment variable $gtm_dist (!AD) could not be verified against the executables path (!AD)", 4,
+ "CRYPTNOAPPEND", "APPEND disallowed on the encrypted file !AD", 2,
+ "CRYPTNOSEEK", "SEEK disallowed on the encrypted file !AD", 2,
+ "CRYPTNOTRUNC", "Not positioned at file start or EOF. TRUNCATE disallowed on the encrypted file !AD", 2,
+ "CRYPTNOKEYSPEC", "Key name needs to be specified with KEY, IKEY, or OKEY device parameter for encrypted I/O", 0,
+ "CRYPTNOOVERRIDE", "Cannot override IVEC and/or key without compromising integrity", 0,
+ "CRYPTKEYTOOBIG", "Specified key has length !UL, which is greater than the maximum allowed key length !UL", 2,
+ "CRYPTBADWRTPOS", "Encrypted WRITE disallowed from a position different than where the last WRITE completed", 0,
+ "LABELNOTFND", "GOTO referenced a label that does not exist", 0,
+ "RELINKCTLERR", "Error with relink control structure for $ZROUTINES directory !AD", 2,
+ "INVLINKTMPDIR", "Value for $gtm_linktmpdir is either not found or not a directory: !AD", 2,
};
LITDEF int ERR_ACK = 150372361;
@@ -1466,7 +1493,7 @@ LITDEF int ERR_GVSUBOFLOW = 150372986;
LITDEF int ERR_GVUNDEF = 150372994;
LITDEF int ERR_TRANSNEST = 150373002;
LITDEF int ERR_INDEXTRACHARS = 150373010;
-LITDEF int ERR_UNUSEDMSG260 = 150373018;
+LITDEF int ERR_CORRUPTNODE = 150373018;
LITDEF int ERR_INDRMAXLEN = 150373026;
LITDEF int ERR_INSFFBCNT = 150373034;
LITDEF int ERR_INTEGERRS = 150373042;
@@ -2015,7 +2042,7 @@ LITDEF int ERR_MUKILLIP = 150377376;
LITDEF int ERR_JNLRDONLY = 150377386;
LITDEF int ERR_ANCOMPTINC = 150377394;
LITDEF int ERR_ABNCOMPTINC = 150377402;
-LITDEF int ERR_UNUSEDMSG809 = 150377410;
+LITDEF int ERR_RECLOAD = 150377410;
LITDEF int ERR_SOCKNOTFND = 150377418;
LITDEF int ERR_CURRSOCKOFR = 150377426;
LITDEF int ERR_SOCKETEXIST = 150377434;
@@ -2039,7 +2066,7 @@ LITDEF int ERR_TOOMANYCLIENTS = 150377570;
LITDEF int ERR_NOEXCLUDE = 150377579;
LITDEF int ERR_GVINCRISOLATION = 150377586;
LITDEF int ERR_EXCLUDEREORG = 150377592;
-LITDEF int ERR_REORGINC = 150377602;
+LITDEF int ERR_REORGINC = 150377600;
LITDEF int ERR_ASC2EBCDICCONV = 150377610;
LITDEF int ERR_GTMSECSHRSTART = 150377618;
LITDEF int ERR_DBVERPERFWARN1 = 150377624;
@@ -2195,16 +2222,16 @@ LITDEF int ERR_REPLJNLCLOSED = 150378818;
LITDEF int ERR_RENAMEFAIL = 150378824;
LITDEF int ERR_FILERENAME = 150378835;
LITDEF int ERR_JNLBUFINFO = 150378843;
-LITDEF int ERR_UNUSEDMSG989 = 150378850;
-LITDEF int ERR_UNUSEDMSG990 = 150378858;
+LITDEF int ERR_SDSEEKERR = 150378850;
+LITDEF int ERR_LOCALSOCKREQ = 150378858;
LITDEF int ERR_TPNOTACID = 150378867;
LITDEF int ERR_JNLSETDATA2LONG = 150378874;
LITDEF int ERR_JNLNEWREC = 150378882;
LITDEF int ERR_REPLFTOKSEM = 150378890;
-LITDEF int ERR_UNUSEDMSG995 = 150378898;
+LITDEF int ERR_SOCKNOTPASSED = 150378898;
LITDEF int ERR_EXTRIOERR = 150378906;
LITDEF int ERR_EXTRCLOSEERR = 150378914;
-LITDEF int ERR_UNUSEDMSG998 = 150378922;
+LITDEF int ERR_CONNSOCKREQ = 150378922;
LITDEF int ERR_REPLEXITERR = 150378930;
LITDEF int ERR_MUDESTROYSUC = 150378939;
LITDEF int ERR_DBRNDWN = 150378946;
@@ -2285,7 +2312,7 @@ LITDEF int ERR_NOSUBSCRIPT = 150379538;
LITDEF int ERR_SYSTEMVALUE = 150379546;
LITDEF int ERR_SIZENOTVALID4 = 150379554;
LITDEF int ERR_STRNOTVALID = 150379562;
-LITDEF int ERR_UNUSEDMSG1079 = 150379570;
+LITDEF int ERR_CREDNOTPASSED = 150379570;
LITDEF int ERR_ERRWETRAP = 150379578;
LITDEF int ERR_TRACINGON = 150379587;
LITDEF int ERR_CITABENV = 150379594;
@@ -2315,7 +2342,7 @@ LITDEF int ERR_GBLNOEXIST = 150379779;
LITDEF int ERR_MAXBTLEVEL = 150379786;
LITDEF int ERR_INVMNEMCSPC = 150379794;
LITDEF int ERR_JNLALIGNSZCHG = 150379803;
-LITDEF int ERR_UNUSEDMSG1109 = 150379810;
+LITDEF int ERR_SEFCTNEEDSFULLB = 150379810;
LITDEF int ERR_GVFAILCORE = 150379818;
LITDEF int ERR_DBCDBNOCERTIFY = 150379826;
LITDEF int ERR_DBFRZRESETSUC = 150379835;
@@ -2462,7 +2489,7 @@ LITDEF int ERR_REPLINSTSEQORD = 150380954;
LITDEF int ERR_REPLINSTSTNDALN = 150380962;
LITDEF int ERR_REPLREQROLLBACK = 150380970;
LITDEF int ERR_REQROLLBACK = 150380978;
-LITDEF int ERR_UNUSEDMSG1256 = 150380986;
+LITDEF int ERR_INVOBJFILE = 150380986;
LITDEF int ERR_SRCSRVEXISTS = 150380994;
LITDEF int ERR_SRCSRVNOTEXIST = 150381002;
LITDEF int ERR_SRCSRVTOOMANY = 150381010;
@@ -2623,7 +2650,7 @@ LITDEF int ERR_EXTRFILEXISTS = 150382242;
LITDEF int ERR_MUUSERECOV = 150382250;
LITDEF int ERR_SECNOTSUPPLEMENTARY = 150382258;
LITDEF int ERR_SUPRCVRNEEDSSUPSRC = 150382266;
-LITDEF int ERR_UNUSEDMSG1417 = 150382275;
+LITDEF int ERR_PEERPIDMISMATCH = 150382274;
LITDEF int ERR_SETITIMERFAILED = 150382284;
LITDEF int ERR_UPDSYNC2MTINS = 150382290;
LITDEF int ERR_UPDSYNCINSTFILE = 150382298;
@@ -2753,9 +2780,36 @@ LITDEF int ERR_TLSCONNINFO = 150383280;
LITDEF int ERR_TLSIOERROR = 150383290;
LITDEF int ERR_TLSRENEGOTIATE = 150383298;
LITDEF int ERR_REPLNOTLS = 150383306;
+LITDEF int ERR_COLTRANSSTR2LONG = 150383314;
+LITDEF int ERR_SOCKPASS = 150383322;
+LITDEF int ERR_SOCKACCEPT = 150383330;
+LITDEF int ERR_NOSOCKHANDLE = 150383338;
+LITDEF int ERR_TRIGLOADFAIL = 150383346;
+LITDEF int ERR_SOCKPASSDATAMIX = 150383354;
+LITDEF int ERR_NOGTCMDB = 150383362;
+LITDEF int ERR_NOUSERDB = 150383370;
+LITDEF int ERR_DSENOTOPEN = 150383378;
+LITDEF int ERR_ZSOCKETATTR = 150383386;
+LITDEF int ERR_ZSOCKETNOTSOCK = 150383394;
+LITDEF int ERR_CHSETALREADY = 150383402;
+LITDEF int ERR_DSEMAXBLKSAV = 150383410;
+LITDEF int ERR_BLKINVALID = 150383418;
+LITDEF int ERR_CANTBITMAP = 150383426;
+LITDEF int ERR_AIMGBLKFAIL = 150383434;
+LITDEF int ERR_GTMDISTUNVERIF = 150383442;
+LITDEF int ERR_CRYPTNOAPPEND = 150383450;
+LITDEF int ERR_CRYPTNOSEEK = 150383458;
+LITDEF int ERR_CRYPTNOTRUNC = 150383466;
+LITDEF int ERR_CRYPTNOKEYSPEC = 150383474;
+LITDEF int ERR_CRYPTNOOVERRIDE = 150383482;
+LITDEF int ERR_CRYPTKEYTOOBIG = 150383490;
+LITDEF int ERR_CRYPTBADWRTPOS = 150383498;
+LITDEF int ERR_LABELNOTFND = 150383506;
+LITDEF int ERR_RELINKCTLERR = 150383514;
+LITDEF int ERR_INVLINKTMPDIR = 150383522;
GBLDEF err_ctl merrors_ctl = {
246,
"GTM",
&merrors[0],
- 1369};
+ 1396};
diff --git a/sr_i386/obj_file.c b/sr_i386/obj_file.c
index 3ff8953..6072f3c 100644
--- a/sr_i386/obj_file.c
+++ b/sr_i386/obj_file.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -61,43 +61,17 @@ static struct rel_table *text_rel, *text_rel_end;
DEBUG_ONLY(static uint4 txtrel_cnt_in_hdr;)
error_def(ERR_OBJFILERR);
+error_def(ERR_STRINGOFLOW);
void create_object_file(rhdtyp *rhead)
{
- int status;
- unsigned char rout_len;
- uint4 stat;
- char obj_name[SIZEOF(mident_fixed) + 5];
- mstr fstr;
- parse_blk pblk;
struct exec hdr;
- error_def(ERR_FILEPARSE);
assert(!run_time);
- memset(&pblk, 0, SIZEOF(pblk));
- pblk.buffer = object_file_name;
- pblk.buff_size = MAX_FBUFF;
- /* create the object file */
- fstr.len = (MV_DEFINED(&cmd_qlf.object_file) ? cmd_qlf.object_file.str.len : 0);
- fstr.addr = cmd_qlf.object_file.str.addr;
- rout_len = module_name.len;
- memcpy(&obj_name[0], module_name.addr, rout_len);
- obj_name[rout_len] = '.';
- obj_name[rout_len + 1] = 'o';
- obj_name[rout_len + 2] = 0;
- pblk.def1_size = rout_len + 2;
- pblk.def1_buf = obj_name;
- status = parse_file(&fstr, &pblk);
- if (!(status & 1))
- rts_error(VARLSTCNT(5) ERR_FILEPARSE, 2, fstr.len, fstr.addr, status);
-
- object_name_len = pblk.b_esl;
- object_file_name[object_name_len] = 0;
-
- OPEN_OBJECT_FILE(object_file_name, O_CREAT | O_RDWR, object_file_des);
- if (FD_INVALID == object_file_des)
- rts_error(VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
+ init_object_file_name(); /* inputs: cmd_qlf.object_file, module_name; outputs: object_file_name, object_name_len */
+ object_file_des = mk_tmp_object_file(object_file_name, object_name_len);
+
memcpy(&rhead->jsb[0], "GTM_CODE", SIZEOF(rhead->jsb));
emit_addr((char *)&rhead->src_full_name.addr - (char *)rhead,
(int4)rhead->src_full_name.addr, (int4 *)&rhead->src_full_name.addr);
@@ -131,7 +105,7 @@ void close_object_file(void)
if (emit_buff_used)
buff_emit();
if ((off_t)-1 == lseek(object_file_des, (off_t)0, SEEK_SET))
- rts_error(VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
}
@@ -245,15 +219,14 @@ void emit_reference(uint4 refaddr, mstr *name, uint4 *result)
* Args: buffer of executable code, and byte count to be output.
*/
-error_def(ERR_STRINGOFLOW);
void emit_immed(char *source, uint4 size)
{
short int write;
if (run_time)
{
- if (stringpool.free + size > stringpool.top)
- rts_error(VARLSTCNT(1) ERR_STRINGOFLOW);
+ if (!IS_STP_SPACE_AVAILABLE(size))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STRINGOFLOW);
memcpy(stringpool.free, source, size);
stringpool.free += size;
} else
@@ -284,7 +257,7 @@ void buff_emit(void)
uint4 stat;
if (-1 == write(object_file_des, emit_buff, emit_buff_used))
- rts_error(VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
emit_buff_used = 0;
}
diff --git a/sr_i386/op_extjmp.s b/sr_i386/op_extjmp.s
index 8391167..be421c4 100644
--- a/sr_i386/op_extjmp.s
+++ b/sr_i386/op_extjmp.s
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2012 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -22,7 +22,7 @@
# PAGE +
.DATA
.extern ERR_GTMCHECK
-.extern ERR_LABELUNKNOWN
+.extern ERR_LABELNOTFND
.extern frame_pointer
.text
@@ -79,7 +79,7 @@ l3: addl $4,%esp
getframe
ret
-l4: pushl ERR_LABELUNKNOWN
+l4: pushl ERR_LABELNOTFND
pushl $1
call rts_error
addl $8,%esp
diff --git a/sr_i386/ttt.c b/sr_i386/ttt.c
index beed698..b22f628 100644
--- a/sr_i386/ttt.c
+++ b/sr_i386/ttt.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,681 +13,686 @@
#include "vxi.h"
#include "vxt.h"
#include "xfer_enum.h"
-LITDEF short ttt[4243] = {
+LITDEF short ttt[4272] = {
-/* 0 */ 0,0,0,0,324,3410,2851,548,
-/* 8 */ 2229,2836,2866,1910,402,3360,2022,2984,
-/* 16 */ 2105,2093,3593,3630,2066,2075,2147,2087,
-/* 24 */ 2138,2117,2045,748,775,763,802,814,
-/* 32 */ 826,844,886,904,922,943,972,1002,
-/* 40 */ 1017,1032,1047,1065,1077,2954,2969,1149,
-/* 48 */ 1182,1215,1254,1317,1368,1644,1659,1674,
-/* 56 */ 1704,1743,1755,1779,1806,1827,1842,3425,
-/* 64 */ 3447,0,0,0,0,563,0,504,
-/* 72 */ 0,1896,0,2940,0,0,0,0,
-/* 80 */ 0,0,356,414,2207,2213,2628,2655,
-/* 88 */ 2673,2776,2714,2705,2791,3499,3583,2887,
-/* 96 */ 0,2919,3050,3013,2998,3028,3374,3226,
-/* 104 */ 3292,3505,3517,3532,3556,3565,3550,3541,
-/* 112 */ 3325,3626,3639,3661,3698,3710,3731,3755,
-/* 120 */ 3821,0,0,2824,2189,3102,4192,636,
-/* 128 */ 4195,690,2685,3068,518,524,4198,2292,
-/* 136 */ 2379,2279,471,2315,2399,2054,2337,2409,
-/* 144 */ 4201,2174,2165,4205,1386,1404,4206,352,
-/* 152 */ 348,3316,426,4210,4213,4216,2905,4219,
-/* 160 */ 4222,4225,4228,4231,4234,3396,0,2800,
-/* 168 */ 2468,2446,1623,2437,2225,2036,2751,1931,
-/* 176 */ 715,2741,0,0,2244,3574,3602,1599,
-/* 184 */ 3526,2327,1924,533,3722,1791,2156,1302,
-/* 192 */ 339,3054,602,668,586,646,3686,1197,
-/* 200 */ 1236,3654,2880,2183,2815,2894,618,1089,
-/* 208 */ 2755,4237,2389,3773,3791,3806,495,2770,
-/* 216 */ 3046,1869,3842,3833,1440,3388,577,1689,
-/* 224 */ 1731,2352,4240,3459,2425,724,862,3085,
-/* 232 */ 3614,3483,3469,3476,3465,700,957,2302,
-/* 240 */ 1131,2266,1119,2126,1104,1164,2364,1569,
-/* 248 */ 1512,1497,1551,1467,1479,1524,1452,1536,
-/* 256 */ 1584,0,3346,0,981,990,3205,3271,
-/* 264 */ 1818,3184,3250,2253,3878,3848,3854,3866,
-/* 272 */ 3888,1341,1353,1275,1287,1329,3437,1719,
-/* 280 */ 1854,3902,3917,3953,3980,3935,3112,3124,
-/* 288 */ 3136,3148,2664,2679,1611,435,790,1422,
-/* 296 */ 627,3160,3172,3965,3971,0,0,0,
-/* 304 */ 0,3677,3992,4003,4015,4024,4038,4051,
-/* 312 */ 4061,4078,4090,4099,4111,4123,4135,4150,
-/* 320 */ 4162,0,0,4171,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,
-/* 328 */ VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,
-/* 336 */ VXT_XFER,SIZEOF(char *) * (short int)xf_add,VXT_END,
-/* 339 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_bindparm,
-/* 347 */ VXT_END,
-/* 348 */ VXI_INCL,VXT_VAL,1,VXT_END,
-/* 352 */ VXI_CLRL,VXT_VAL,0,VXT_END,
-/* 356 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_break,VXT_END,
-/* 360 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callb,VXI_BRB,VXT_JMP,1,VXT_END,
-/* 367 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_calll,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 374 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callw,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 381 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspb,VXI_BRB,VXT_JMP,1,VXT_END,
-/* 388 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspl,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 395 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspw,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 402 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 410 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_cat,VXT_END,
-/* 414 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 422 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_close,VXT_END,
-/* 426 */ VXI_BICB2,VXT_LIT,1,VXT_REG,0x5A,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_dt_false,
-/* 434 */ VXT_END,
-/* 435 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_clralsvars,
-/* 443 */ VXT_END,
-/* 444 */ VXI_TSTL,VXT_VAL,1,VXT_END,
-/* 448 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2bool,
-/* 456 */ VXT_END,
-/* 457 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2mint,
-/* 465 */ VXI_MOVL,VXT_REG,0x50,VXT_VAL,0,VXT_END,
-/* 471 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 479 */ SIZEOF(char *) * (short int)xf_commarg,VXT_END,
-/* 481 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVL,VXT_VAL,1,
-/* 489 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mint2mval,VXT_END,
-/* 495 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2num,
-/* 503 */ VXT_END,
-/* 504 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 512 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_contain,VXT_END,
-/* 518 */ VXI_MOVL,VXT_REG,0x6C,VXT_ADDR,0,VXT_END,
-/* 524 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_currtn,
-/* 532 */ VXT_END,
-/* 533 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 541 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_cvtparm,VXT_END,
-/* 548 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 556 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_div,VXT_END,
-/* 563 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
-/* 571 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equ,VXT_END,
-/* 577 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equnul,
-/* 585 */ VXT_END,
-/* 586 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 594 */ 2,VXI_PUSHL,VXT_LIT,0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
-/* 602 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 610 */ 2,VXI_PUSHAB,VXT_VAL,0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
-/* 618 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunret,
-/* 626 */ VXT_END,
-/* 627 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunretals,
-/* 635 */ VXT_END,
-/* 636 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 644 */ SIZEOF(char *) * (short int)xf_extcall,VXT_END,
-/* 646 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 654 */ 3,VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 662 */ VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
-/* 668 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 676 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 684 */ VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
-/* 690 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 698 */ SIZEOF(char *) * (short int)xf_extjmp,VXT_END,
-/* 700 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 708 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_exp,VXT_END,
-/* 715 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fetch,
-/* 723 */ VXT_END,
-/* 724 */ VXT_IREPAB,VXT_VAL,6,VXI_PUSHL,VXT_VAL,5,VXI_PUSHL,VXT_VAL,
-/* 732 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,
-/* 740 */ VXT_LIT,0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
-/* 748 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 756 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnascii,VXT_END,
-/* 763 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 771 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnchar,VXT_END,
-/* 775 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 783 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzascii,VXT_END,
-/* 790 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 798 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzahandle,VXT_END,
-/* 802 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 810 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzchar,VXT_END,
-/* 814 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 822 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fndata,VXT_END,
-/* 826 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 834 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 842 */ SIZEOF(char *) * (short int)xf_fnextract,VXT_END,
-/* 844 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 852 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 860 */ SIZEOF(char *) * (short int)xf_fnzextract,VXT_END,
-/* 862 */ VXT_IREPAB,VXT_VAL,6,VXI_PUSHL,VXT_VAL,5,VXI_PUSHL,VXT_VAL,
-/* 870 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 878 */ VXT_VAL,0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
-/* 886 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 894 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 902 */ SIZEOF(char *) * (short int)xf_fnfind,VXT_END,
-/* 904 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 912 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 920 */ SIZEOF(char *) * (short int)xf_fnzfind,VXT_END,
-/* 922 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 930 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 938 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfnumber,VXT_END,
-/* 943 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
-/* 951 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget,VXT_END,
-/* 957 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 965 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget2,VXT_END,
-/* 972 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget,
-/* 980 */ VXT_END,
-/* 981 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget1,
-/* 989 */ VXT_END,
-/* 990 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 998 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget1,VXT_END,
-/* 1002 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1010 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnincr,VXT_END,
-/* 1017 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1025 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnj2,VXT_END,
-/* 1032 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1040 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzj2,VXT_END,
-/* 1047 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1055 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1063 */ SIZEOF(char *) * (short int)xf_fnj3,VXT_END,
-/* 1065 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1073 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlength,VXT_END,
-/* 1077 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1085 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlength,VXT_END,
-/* 1089 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1097 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvname,VXT_END,
-/* 1104 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
-/* 1112 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvnameo2,VXT_END,
-/* 1119 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1127 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvprvname,VXT_END,
-/* 1131 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 1139 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,2,VXT_XFER,
-/* 1147 */ SIZEOF(char *) * (short int)xf_fnname,VXT_END,
-/* 1149 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1157 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnnext,VXT_END,
-/* 1164 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
-/* 1172 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1180 */ SIZEOF(char *) * (short int)xf_fno2,VXT_END,
-/* 1182 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1190 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnorder,VXT_END,
-/* 1197 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1205 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1213 */ SIZEOF(char *) * (short int)xf_fnp1,VXT_END,
-/* 1215 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 1223 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1231 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpiece,VXT_END,
-/* 1236 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1244 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1252 */ SIZEOF(char *) * (short int)xf_fnzp1,VXT_END,
-/* 1254 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 1262 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1270 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpiece,VXT_END,
-/* 1275 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1283 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqlength,VXT_END,
-/* 1287 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1295 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqsubscript,VXT_END,
-/* 1302 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1310 */ 0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnquery,VXT_END,
-/* 1317 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1325 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnrandom,VXT_END,
-/* 1329 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1337 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnreverse,VXT_END,
-/* 1341 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1349 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack1,VXT_END,
-/* 1353 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1361 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack2,VXT_END,
-/* 1368 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1376 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1384 */ SIZEOF(char *) * (short int)xf_fntext,VXT_END,
-/* 1386 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1394 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1402 */ SIZEOF(char *) * (short int)xf_fntranslate,VXT_END,
-/* 1404 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1412 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1420 */ SIZEOF(char *) * (short int)xf_fnztranslate,VXT_END,
-/* 1422 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1430 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1438 */ SIZEOF(char *) * (short int)xf_fnztrigger,VXT_END,
-/* 1440 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 1448 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnview,VXT_END,
-/* 1452 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1460 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitand,VXT_END,
-/* 1467 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1475 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitcoun,VXT_END,
-/* 1479 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1487 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1495 */ SIZEOF(char *) * (short int)xf_fnzbitfind,VXT_END,
-/* 1497 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1505 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitget,VXT_END,
-/* 1512 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1520 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitlen,VXT_END,
-/* 1524 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1532 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitnot,VXT_END,
-/* 1536 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1544 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitor,VXT_END,
-/* 1551 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1559 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1567 */ SIZEOF(char *) * (short int)xf_fnzbitset,VXT_END,
-/* 1569 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1577 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitstr,VXT_END,
-/* 1584 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1592 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitxor,VXT_END,
-/* 1599 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 1607 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzcall,VXT_END,
-/* 1611 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1619 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdata,VXT_END,
-/* 1623 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
-/* 1631 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1639 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdate,VXT_END,
-/* 1644 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1652 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzfile,VXT_END,
-/* 1659 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1667 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetdvi,VXT_END,
-/* 1674 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1682 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetjpi,VXT_END,
-/* 1689 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1697 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetlki,VXT_END,
-/* 1704 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1712 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetsyi,VXT_END,
-/* 1719 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1727 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzjobexam,VXT_END,
-/* 1731 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1739 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlkid,VXT_END,
-/* 1743 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1751 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzm,VXT_END,
-/* 1755 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
-/* 1763 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 1771 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzparse,VXT_END,
-/* 1779 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1787 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpid,VXT_END,
-/* 1791 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1799 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzprevious,VXT_END,
-/* 1806 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1814 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpriv,VXT_END,
-/* 1818 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzqgblmod,
-/* 1826 */ VXT_END,
-/* 1827 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1835 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsearch,VXT_END,
-/* 1842 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1850 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsetprv,VXT_END,
-/* 1854 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1862 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsigproc,VXT_END,
-/* 1869 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,6,VXI_PUSHAB,VXT_VAL,
-/* 1877 */ 5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,
-/* 1885 */ VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,7,
-/* 1893 */ VXT_XFER,SIZEOF(char *) * (short int)xf_fnztrnlnm,VXT_END,
-/* 1896 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 1904 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_follow,VXT_END,
-/* 1910 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
-/* 1918 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forcenum,VXT_END,
-/* 1924 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forchk1,VXT_END,
-/* 1931 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1939 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forinit,VXT_END,
-/* 1944 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldob,VXI_BRB,VXT_JMP,1,VXT_END,
-/* 1951 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldol,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 1958 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldow,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 1965 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 1973 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 1981 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 1984 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 1992 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 2000 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 2003 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 2011 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 2019 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 2022 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_getindx,
-/* 2030 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 2036 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_gettruth,
-/* 2044 */ VXT_END,
-/* 2045 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvdata,
-/* 2053 */ VXT_END,
-/* 2054 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2062 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvextnam,VXT_END,
-/* 2066 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvget,
-/* 2074 */ VXT_END,
-/* 2075 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 2083 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvincr,VXT_END,
-/* 2087 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvkill,VXT_END,
-/* 2093 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2101 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnaked,VXT_END,
-/* 2105 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2113 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvname,VXT_END,
-/* 2117 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnext,
-/* 2125 */ VXT_END,
-/* 2126 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 2134 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvo2,VXT_END,
-/* 2138 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvorder,
-/* 2146 */ VXT_END,
-/* 2147 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvput,
-/* 2155 */ VXT_END,
-/* 2156 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvquery,
-/* 2164 */ VXT_END,
-/* 2165 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvrectarg,
-/* 2173 */ VXT_END,
-/* 2174 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvsavtarg,
-/* 2182 */ VXT_END,
-/* 2183 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvzwithdraw,VXT_END,
-/* 2189 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 2197 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,
-/* 2205 */ SIZEOF(char *) * (short int)xf_gvzwrite,VXT_END,
-/* 2207 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_halt,VXT_END,
-/* 2213 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 2221 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_hang,VXT_END,
-/* 2225 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_hardret,VXT_END,
-/* 2229 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2237 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_idiv,VXT_END,
-/* 2244 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_igetsrc,
-/* 2252 */ VXT_END,
-/* 2253 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2261 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_inddevparms,VXT_END,
-/* 2266 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2274 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname,VXT_END,
-/* 2279 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2287 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfun,VXT_END,
-/* 2292 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2300 */ SIZEOF(char *) * (short int)xf_indglvn,VXT_END,
-/* 2302 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2310 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indincr,VXT_END,
-/* 2315 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvadr,VXI_MOVL,VXT_REG,
-/* 2323 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2327 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2335 */ SIZEOF(char *) * (short int)xf_indlvarg,VXT_END,
-/* 2337 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2345 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indname,VXT_END,
-/* 2352 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvnamadr,VXI_MOVL,VXT_REG,
-/* 2360 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2364 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2372 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indo2,VXT_END,
-/* 2379 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2387 */ SIZEOF(char *) * (short int)xf_indpat,VXT_END,
-/* 2389 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2397 */ SIZEOF(char *) * (short int)xf_indrzshow,VXT_END,
-/* 2399 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2407 */ SIZEOF(char *) * (short int)xf_indset,VXT_END,
-/* 2409 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2417 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indtext,VXT_END,
-/* 2425 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2433 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_iocontrol,VXT_END,
-/* 2437 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_iretmvad,
-/* 2445 */ VXT_END,
-/* 2446 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2454 */ SIZEOF(char *) * (short int)xf_iretmval,VXT_END,
-/* 2456 */ VXI_BRB,VXT_JMP,1,VXT_END,
-/* 2460 */ VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2464 */ VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2468 */ VXI_JMP,VXT_VAL,1,VXT_END,
-/* 2472 */ VXI_BEQL,VXT_JMP,1,VXT_END,
-/* 2476 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2483 */ VXI_BNEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2490 */ VXI_BGEQ,VXT_JMP,1,VXT_END,
-/* 2494 */ VXI_BLSS,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2501 */ VXI_BLSS,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2508 */ VXI_BGTR,VXT_JMP,1,VXT_END,
-/* 2512 */ VXI_BLEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2519 */ VXI_BLEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2526 */ VXI_BLEQ,VXT_JMP,1,VXT_END,
-/* 2530 */ VXI_BGTR,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2537 */ VXI_BGTR,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2544 */ VXI_BLSS,VXT_JMP,1,VXT_END,
-/* 2548 */ VXI_BGEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2555 */ VXI_BGEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2562 */ VXI_BNEQ,VXT_JMP,1,VXT_END,
-/* 2566 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2573 */ VXI_BEQL,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2580 */ VXI_BLBC,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
-/* 2586 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
-/* 2594 */ VXT_END,
-/* 2595 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
-/* 2603 */ VXT_END,
-/* 2604 */ VXI_BLBS,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
-/* 2610 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
-/* 2618 */ VXT_END,
-/* 2619 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
-/* 2627 */ VXT_END,
-/* 2628 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,7,VXI_PUSHL,VXT_VAL,
-/* 2636 */ 6,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,
-/* 2644 */ VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,
-/* 2652 */ VXT_XFER,SIZEOF(char *) * (short int)xf_job,VXT_END,
-/* 2655 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_kill,
-/* 2663 */ VXT_END,
-/* 2664 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_killalias,
-/* 2672 */ VXT_END,
-/* 2673 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killall,VXT_END,
-/* 2679 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killaliasall,VXT_END,
-/* 2685 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2693 */ 3,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_labaddr,VXI_MOVL,VXT_REG,
-/* 2701 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2705 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckdecr,
-/* 2713 */ VXT_END,
-/* 2714 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckincr,
-/* 2722 */ VXT_END,
-/* 2723 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2729 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2735 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2741 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2749 */ SIZEOF(char *) * (short int)xf_linefetch,VXT_END,
-/* 2751 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_linestart,VXT_END,
-/* 2755 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 2763 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
-/* 2770 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_lkinit,VXT_END,
-/* 2776 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2784 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
-/* 2791 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lock,
-/* 2799 */ VXT_END,
-/* 2800 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2808 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvpatwrite,VXT_END,
-/* 2815 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwithdraw,
-/* 2823 */ VXT_END,
-/* 2824 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2832 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwrite,VXT_END,
-/* 2836 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2844 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_flt_mod,VXT_END,
-/* 2851 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2859 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_mul,VXT_END,
-/* 2866 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
-/* 2874 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_neg,VXT_END,
-/* 2880 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newintrinsic,VXT_END,
-/* 2887 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newvar,VXT_END,
-/* 2894 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_nullexp,VXI_MOVL,VXT_REG,0x50,
-/* 2902 */ VXT_ADDR,0,VXT_END,
-/* 2905 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 2913 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_numcmp,VXT_END,
-/* 2919 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 2927 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 2935 */ VXT_LIT,4,VXT_XFER,SIZEOF(char *) * (short int)xf_open,VXT_END,
-/* 2940 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 2948 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_pattern,VXT_END,
-/* 2954 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2962 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpopulation,VXT_END,
-/* 2969 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2977 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpopulation,VXT_END,
-/* 2984 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_putindx,
-/* 2992 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 2998 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 3006 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_rdone,VXT_END,
-/* 3013 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 3021 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_read,VXT_END,
-/* 3028 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 3036 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,3,VXT_XFER,
-/* 3044 */ SIZEOF(char *) * (short int)xf_readfl,VXT_END,
-/* 3046 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_END,
-/* 3050 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_ret,VXT_END,
-/* 3054 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVL,VXT_VAL,2,
-/* 3062 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_retarg,VXT_END,
-/* 3068 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3076 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 3084 */ VXT_END,
-/* 3085 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 0 */ 0,0,0,0,326,3427,2868,550,
+/* 8 */ 2246,2853,2883,1927,404,3377,2039,3001,
+/* 16 */ 2122,2110,3610,3647,2083,2092,2164,2104,
+/* 24 */ 2155,2134,2062,750,777,765,804,816,
+/* 32 */ 828,846,888,906,924,945,974,1004,
+/* 40 */ 1019,1034,1049,1067,1079,2971,2986,1151,
+/* 48 */ 1184,1217,1256,1319,1370,1646,1661,1676,
+/* 56 */ 1706,1745,1757,1781,1808,1829,1847,3442,
+/* 64 */ 3464,0,0,0,0,565,0,506,
+/* 72 */ 0,1913,0,2957,0,0,0,0,
+/* 80 */ 0,0,358,416,2224,2230,2645,2672,
+/* 88 */ 2690,2793,2731,2722,2808,3516,3600,2904,
+/* 96 */ 0,2936,3067,3030,3015,3045,3391,3243,
+/* 104 */ 3309,3522,3534,3549,3573,3582,3567,3558,
+/* 112 */ 3342,3643,3656,3678,3715,3727,3748,3772,
+/* 120 */ 3838,0,0,2841,2206,3119,4221,638,
+/* 128 */ 4224,692,2702,3085,520,526,4227,2309,
+/* 136 */ 2396,2296,473,2332,2416,2071,2354,2426,
+/* 144 */ 4230,2191,2182,4234,1388,1406,4235,354,
+/* 152 */ 350,3333,428,4239,4242,4245,2922,4248,
+/* 160 */ 4251,4254,4257,4260,4263,3413,0,2817,
+/* 168 */ 2485,2463,1625,2454,2242,2053,2768,1948,
+/* 176 */ 717,2758,0,0,2261,3591,3619,1601,
+/* 184 */ 3543,2344,1941,535,3739,1793,2173,1304,
+/* 192 */ 341,3071,604,670,588,648,3703,1199,
+/* 200 */ 1238,3671,2897,2200,2832,2911,620,1091,
+/* 208 */ 2772,4266,2406,3790,3808,3823,497,2787,
+/* 216 */ 3063,1886,3859,3850,1442,3405,579,1691,
+/* 224 */ 1733,2369,4269,3476,2442,726,864,3102,
+/* 232 */ 3631,3500,3486,3493,3482,702,959,2319,
+/* 240 */ 1133,2283,1121,2143,1106,1166,2381,1571,
+/* 248 */ 1514,1499,1553,1469,1481,1526,1454,1538,
+/* 256 */ 1586,0,3363,0,983,992,3222,3288,
+/* 264 */ 1820,3201,3267,2270,3895,3865,3871,3883,
+/* 272 */ 3905,1343,1355,1277,1289,1331,3454,1721,
+/* 280 */ 1859,3919,3934,3970,3997,3952,3129,3141,
+/* 288 */ 3153,3165,2681,2696,1613,437,792,1424,
+/* 296 */ 629,3177,3189,3982,3988,0,0,0,
+/* 304 */ 0,3694,4009,4020,4032,4041,4055,4068,
+/* 312 */ 4078,4095,4107,4116,4128,4140,4152,4167,
+/* 320 */ 4179,0,0,4188,4209,1874,VXI_PUSHAB,VXT_VAL,
+/* 328 */ 0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 336 */ VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_add,VXT_END,
+/* 341 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_bindparm,
+/* 349 */ VXT_END,
+/* 350 */ VXI_INCL,VXT_VAL,1,VXT_END,
+/* 354 */ VXI_CLRL,VXT_VAL,0,VXT_END,
+/* 358 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_break,VXT_END,
+/* 362 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callb,VXI_BRB,VXT_JMP,1,VXT_END,
+/* 369 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_calll,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 376 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callw,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 383 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspb,VXI_BRB,VXT_JMP,1,VXT_END,
+/* 390 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspl,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 397 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspw,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 404 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 412 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_cat,VXT_END,
+/* 416 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 424 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_close,VXT_END,
+/* 428 */ VXI_BICB2,VXT_LIT,1,VXT_REG,0x5A,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_dt_false,
+/* 436 */ VXT_END,
+/* 437 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_clralsvars,
+/* 445 */ VXT_END,
+/* 446 */ VXI_TSTL,VXT_VAL,1,VXT_END,
+/* 450 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2bool,
+/* 458 */ VXT_END,
+/* 459 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2mint,
+/* 467 */ VXI_MOVL,VXT_REG,0x50,VXT_VAL,0,VXT_END,
+/* 473 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 481 */ SIZEOF(char *) * (short int)xf_commarg,VXT_END,
+/* 483 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVL,VXT_VAL,1,
+/* 491 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mint2mval,VXT_END,
+/* 497 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2num,
+/* 505 */ VXT_END,
+/* 506 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 514 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_contain,VXT_END,
+/* 520 */ VXI_MOVL,VXT_REG,0x6C,VXT_ADDR,0,VXT_END,
+/* 526 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_currtn,
+/* 534 */ VXT_END,
+/* 535 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 543 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_cvtparm,VXT_END,
+/* 550 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 558 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_div,VXT_END,
+/* 565 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
+/* 573 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equ,VXT_END,
+/* 579 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equnul,
+/* 587 */ VXT_END,
+/* 588 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 596 */ 2,VXI_PUSHL,VXT_LIT,0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
+/* 604 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 612 */ 2,VXI_PUSHAB,VXT_VAL,0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
+/* 620 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunret,
+/* 628 */ VXT_END,
+/* 629 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunretals,
+/* 637 */ VXT_END,
+/* 638 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 646 */ SIZEOF(char *) * (short int)xf_extcall,VXT_END,
+/* 648 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 656 */ 3,VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 664 */ VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
+/* 670 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 678 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 686 */ VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
+/* 692 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 700 */ SIZEOF(char *) * (short int)xf_extjmp,VXT_END,
+/* 702 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 710 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_exp,VXT_END,
+/* 717 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fetch,
+/* 725 */ VXT_END,
+/* 726 */ VXT_IREPAB,VXT_VAL,6,VXI_PUSHL,VXT_VAL,5,VXI_PUSHL,VXT_VAL,
+/* 734 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,
+/* 742 */ VXT_LIT,0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
+/* 750 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 758 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnascii,VXT_END,
+/* 765 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 773 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnchar,VXT_END,
+/* 777 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 785 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzascii,VXT_END,
+/* 792 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 800 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzahandle,VXT_END,
+/* 804 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 812 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzchar,VXT_END,
+/* 816 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 824 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fndata,VXT_END,
+/* 828 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 836 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 844 */ SIZEOF(char *) * (short int)xf_fnextract,VXT_END,
+/* 846 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 854 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 862 */ SIZEOF(char *) * (short int)xf_fnzextract,VXT_END,
+/* 864 */ VXT_IREPAB,VXT_VAL,6,VXI_PUSHL,VXT_VAL,5,VXI_PUSHL,VXT_VAL,
+/* 872 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 880 */ VXT_VAL,0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
+/* 888 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 896 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 904 */ SIZEOF(char *) * (short int)xf_fnfind,VXT_END,
+/* 906 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 914 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 922 */ SIZEOF(char *) * (short int)xf_fnzfind,VXT_END,
+/* 924 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 932 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 940 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfnumber,VXT_END,
+/* 945 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
+/* 953 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget,VXT_END,
+/* 959 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 967 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget2,VXT_END,
+/* 974 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget,
+/* 982 */ VXT_END,
+/* 983 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget1,
+/* 991 */ VXT_END,
+/* 992 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1000 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget1,VXT_END,
+/* 1004 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1012 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnincr,VXT_END,
+/* 1019 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1027 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnj2,VXT_END,
+/* 1034 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1042 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzj2,VXT_END,
+/* 1049 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1057 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1065 */ SIZEOF(char *) * (short int)xf_fnj3,VXT_END,
+/* 1067 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1075 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlength,VXT_END,
+/* 1079 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1087 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlength,VXT_END,
+/* 1091 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1099 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvname,VXT_END,
+/* 1106 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
+/* 1114 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvnameo2,VXT_END,
+/* 1121 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1129 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvprvname,VXT_END,
+/* 1133 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 1141 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,2,VXT_XFER,
+/* 1149 */ SIZEOF(char *) * (short int)xf_fnname,VXT_END,
+/* 1151 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1159 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnnext,VXT_END,
+/* 1166 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
+/* 1174 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1182 */ SIZEOF(char *) * (short int)xf_fno2,VXT_END,
+/* 1184 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1192 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnorder,VXT_END,
+/* 1199 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1207 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1215 */ SIZEOF(char *) * (short int)xf_fnp1,VXT_END,
+/* 1217 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 1225 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1233 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpiece,VXT_END,
+/* 1238 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1246 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1254 */ SIZEOF(char *) * (short int)xf_fnzp1,VXT_END,
+/* 1256 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 1264 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1272 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpiece,VXT_END,
+/* 1277 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1285 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqlength,VXT_END,
+/* 1289 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1297 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqsubscript,VXT_END,
+/* 1304 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1312 */ 0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnquery,VXT_END,
+/* 1319 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1327 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnrandom,VXT_END,
+/* 1331 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1339 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnreverse,VXT_END,
+/* 1343 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1351 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack1,VXT_END,
+/* 1355 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1363 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack2,VXT_END,
+/* 1370 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1378 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1386 */ SIZEOF(char *) * (short int)xf_fntext,VXT_END,
+/* 1388 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1396 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1404 */ SIZEOF(char *) * (short int)xf_fntranslate,VXT_END,
+/* 1406 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1414 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1422 */ SIZEOF(char *) * (short int)xf_fnztranslate,VXT_END,
+/* 1424 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1432 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1440 */ SIZEOF(char *) * (short int)xf_fnztrigger,VXT_END,
+/* 1442 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1450 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnview,VXT_END,
+/* 1454 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1462 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitand,VXT_END,
+/* 1469 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1477 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitcoun,VXT_END,
+/* 1481 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1489 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1497 */ SIZEOF(char *) * (short int)xf_fnzbitfind,VXT_END,
+/* 1499 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1507 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitget,VXT_END,
+/* 1514 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1522 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitlen,VXT_END,
+/* 1526 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1534 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitnot,VXT_END,
+/* 1538 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1546 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitor,VXT_END,
+/* 1553 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1561 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1569 */ SIZEOF(char *) * (short int)xf_fnzbitset,VXT_END,
+/* 1571 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1579 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitstr,VXT_END,
+/* 1586 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1594 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitxor,VXT_END,
+/* 1601 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1609 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzcall,VXT_END,
+/* 1613 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1621 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdata,VXT_END,
+/* 1625 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
+/* 1633 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1641 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdate,VXT_END,
+/* 1646 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1654 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzfile,VXT_END,
+/* 1661 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1669 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetdvi,VXT_END,
+/* 1676 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1684 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetjpi,VXT_END,
+/* 1691 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1699 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetlki,VXT_END,
+/* 1706 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1714 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetsyi,VXT_END,
+/* 1721 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1729 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzjobexam,VXT_END,
+/* 1733 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1741 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlkid,VXT_END,
+/* 1745 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1753 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzm,VXT_END,
+/* 1757 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
+/* 1765 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 1773 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzparse,VXT_END,
+/* 1781 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1789 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpid,VXT_END,
+/* 1793 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1801 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzprevious,VXT_END,
+/* 1808 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1816 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpriv,VXT_END,
+/* 1820 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzqgblmod,
+/* 1828 */ VXT_END,
+/* 1829 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1837 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1845 */ SIZEOF(char *) * (short int)xf_fnzsearch,VXT_END,
+/* 1847 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1855 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsetprv,VXT_END,
+/* 1859 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1867 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsigproc,VXT_END,
+/* 1874 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1882 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsocket,VXT_END,
+/* 1886 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,6,VXI_PUSHAB,VXT_VAL,
+/* 1894 */ 5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,
+/* 1902 */ VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,7,
+/* 1910 */ VXT_XFER,SIZEOF(char *) * (short int)xf_fnztrnlnm,VXT_END,
+/* 1913 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 1921 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_follow,VXT_END,
+/* 1927 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
+/* 1935 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forcenum,VXT_END,
+/* 1941 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forchk1,VXT_END,
+/* 1948 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1956 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forinit,VXT_END,
+/* 1961 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldob,VXI_BRB,VXT_JMP,1,VXT_END,
+/* 1968 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldol,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 1975 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldow,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 1982 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 1990 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 1998 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2001 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 2009 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 2017 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2020 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 2028 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 2036 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2039 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_getindx,
+/* 2047 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 2053 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_gettruth,
+/* 2061 */ VXT_END,
+/* 2062 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvdata,
+/* 2070 */ VXT_END,
+/* 2071 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2079 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvextnam,VXT_END,
+/* 2083 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvget,
+/* 2091 */ VXT_END,
+/* 2092 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 2100 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvincr,VXT_END,
+/* 2104 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvkill,VXT_END,
+/* 2110 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2118 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnaked,VXT_END,
+/* 2122 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2130 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvname,VXT_END,
+/* 2134 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnext,
+/* 2142 */ VXT_END,
+/* 2143 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 2151 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvo2,VXT_END,
+/* 2155 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvorder,
+/* 2163 */ VXT_END,
+/* 2164 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvput,
+/* 2172 */ VXT_END,
+/* 2173 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvquery,
+/* 2181 */ VXT_END,
+/* 2182 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvrectarg,
+/* 2190 */ VXT_END,
+/* 2191 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvsavtarg,
+/* 2199 */ VXT_END,
+/* 2200 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvzwithdraw,VXT_END,
+/* 2206 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 2214 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,
+/* 2222 */ SIZEOF(char *) * (short int)xf_gvzwrite,VXT_END,
+/* 2224 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_halt,VXT_END,
+/* 2230 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 2238 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_hang,VXT_END,
+/* 2242 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_hardret,VXT_END,
+/* 2246 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2254 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_idiv,VXT_END,
+/* 2261 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_igetsrc,
+/* 2269 */ VXT_END,
+/* 2270 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2278 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_inddevparms,VXT_END,
+/* 2283 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2291 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname,VXT_END,
+/* 2296 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2304 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfun,VXT_END,
+/* 2309 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2317 */ SIZEOF(char *) * (short int)xf_indglvn,VXT_END,
+/* 2319 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2327 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indincr,VXT_END,
+/* 2332 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvadr,VXI_MOVL,VXT_REG,
+/* 2340 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2344 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2352 */ SIZEOF(char *) * (short int)xf_indlvarg,VXT_END,
+/* 2354 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2362 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indname,VXT_END,
+/* 2369 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvnamadr,VXI_MOVL,VXT_REG,
+/* 2377 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2381 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2389 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indo2,VXT_END,
+/* 2396 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2404 */ SIZEOF(char *) * (short int)xf_indpat,VXT_END,
+/* 2406 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2414 */ SIZEOF(char *) * (short int)xf_indrzshow,VXT_END,
+/* 2416 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2424 */ SIZEOF(char *) * (short int)xf_indset,VXT_END,
+/* 2426 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2434 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indtext,VXT_END,
+/* 2442 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2450 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_iocontrol,VXT_END,
+/* 2454 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_iretmvad,
+/* 2462 */ VXT_END,
+/* 2463 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2471 */ SIZEOF(char *) * (short int)xf_iretmval,VXT_END,
+/* 2473 */ VXI_BRB,VXT_JMP,1,VXT_END,
+/* 2477 */ VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2481 */ VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2485 */ VXI_JMP,VXT_VAL,1,VXT_END,
+/* 2489 */ VXI_BEQL,VXT_JMP,1,VXT_END,
+/* 2493 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2500 */ VXI_BNEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2507 */ VXI_BGEQ,VXT_JMP,1,VXT_END,
+/* 2511 */ VXI_BLSS,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2518 */ VXI_BLSS,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2525 */ VXI_BGTR,VXT_JMP,1,VXT_END,
+/* 2529 */ VXI_BLEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2536 */ VXI_BLEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2543 */ VXI_BLEQ,VXT_JMP,1,VXT_END,
+/* 2547 */ VXI_BGTR,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2554 */ VXI_BGTR,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2561 */ VXI_BLSS,VXT_JMP,1,VXT_END,
+/* 2565 */ VXI_BGEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2572 */ VXI_BGEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2579 */ VXI_BNEQ,VXT_JMP,1,VXT_END,
+/* 2583 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2590 */ VXI_BEQL,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2597 */ VXI_BLBC,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
+/* 2603 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
+/* 2611 */ VXT_END,
+/* 2612 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
+/* 2620 */ VXT_END,
+/* 2621 */ VXI_BLBS,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
+/* 2627 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
+/* 2635 */ VXT_END,
+/* 2636 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
+/* 2644 */ VXT_END,
+/* 2645 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,7,VXI_PUSHL,VXT_VAL,
+/* 2653 */ 6,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,
+/* 2661 */ VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,
+/* 2669 */ VXT_XFER,SIZEOF(char *) * (short int)xf_job,VXT_END,
+/* 2672 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_kill,
+/* 2680 */ VXT_END,
+/* 2681 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_killalias,
+/* 2689 */ VXT_END,
+/* 2690 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killall,VXT_END,
+/* 2696 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killaliasall,VXT_END,
+/* 2702 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2710 */ 3,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_labaddr,VXI_MOVL,VXT_REG,
+/* 2718 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2722 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckdecr,
+/* 2730 */ VXT_END,
+/* 2731 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckincr,
+/* 2739 */ VXT_END,
+/* 2740 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2746 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2752 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2758 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2766 */ SIZEOF(char *) * (short int)xf_linefetch,VXT_END,
+/* 2768 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_linestart,VXT_END,
+/* 2772 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 2780 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
+/* 2787 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_lkinit,VXT_END,
+/* 2793 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2801 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
+/* 2808 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lock,
+/* 2816 */ VXT_END,
+/* 2817 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2825 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvpatwrite,VXT_END,
+/* 2832 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwithdraw,
+/* 2840 */ VXT_END,
+/* 2841 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2849 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwrite,VXT_END,
+/* 2853 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2861 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_flt_mod,VXT_END,
+/* 2868 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2876 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_mul,VXT_END,
+/* 2883 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
+/* 2891 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_neg,VXT_END,
+/* 2897 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newintrinsic,VXT_END,
+/* 2904 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newvar,VXT_END,
+/* 2911 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_nullexp,VXI_MOVL,VXT_REG,0x50,
+/* 2919 */ VXT_ADDR,0,VXT_END,
+/* 2922 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 2930 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_numcmp,VXT_END,
+/* 2936 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 2944 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 2952 */ VXT_LIT,4,VXT_XFER,SIZEOF(char *) * (short int)xf_open,VXT_END,
+/* 2957 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 2965 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_pattern,VXT_END,
+/* 2971 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2979 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpopulation,VXT_END,
+/* 2986 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2994 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpopulation,VXT_END,
+/* 3001 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_putindx,
+/* 3009 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3015 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 3023 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_rdone,VXT_END,
+/* 3030 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 3038 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_read,VXT_END,
+/* 3045 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 3053 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,3,VXT_XFER,
+/* 3061 */ SIZEOF(char *) * (short int)xf_readfl,VXT_END,
+/* 3063 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_END,
+/* 3067 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_ret,VXT_END,
+/* 3071 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVL,VXT_VAL,2,
+/* 3079 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_retarg,VXT_END,
+/* 3085 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
/* 3093 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
/* 3101 */ VXT_END,
-/* 3102 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3110 */ SIZEOF(char *) * (short int)xf_rterror,VXT_END,
-/* 3112 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3120 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setals2als,VXT_END,
-/* 3124 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3132 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsin2alsct,VXT_END,
-/* 3136 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3144 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsctin2als,VXT_END,
-/* 3148 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3156 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsct2alsct,VXT_END,
-/* 3160 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3168 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2als,VXT_END,
-/* 3172 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3180 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2alsct,VXT_END,
-/* 3184 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3192 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3200 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setextract,VXT_END,
-/* 3205 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3213 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3221 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setp1,VXT_END,
-/* 3226 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3234 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3242 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setpiece,VXT_END,
-/* 3250 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3258 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3266 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzextract,VXT_END,
-/* 3271 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3279 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3287 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzp1,VXT_END,
-/* 3292 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3300 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3308 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setzpiece,VXT_END,
-/* 3316 */ VXI_BISB2,VXT_LIT,1,VXT_REG,0x5A,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_dt_true,
-/* 3324 */ VXT_END,
-/* 3325 */ VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3333 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,3,VXI_CALLS,
-/* 3341 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzbrk,VXT_END,
-/* 3346 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 3354 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sorts_after,VXT_END,
-/* 3360 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_srchindx,
-/* 3368 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 3374 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
-/* 3382 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
-/* 3388 */ VXI_MOVC3,VXT_LIT,16,VXT_VAL,2,VXT_VAL,1,VXT_END,
-/* 3396 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
-/* 3404 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
-/* 3410 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3418 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_sub,VXT_END,
-/* 3425 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3433 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svget,VXT_END,
-/* 3437 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3445 */ SIZEOF(char *) * (short int)xf_psvput,VXT_END,
-/* 3447 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3455 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svput,VXT_END,
-/* 3459 */ VXI_MOVL,VXT_REG,0x50,VXT_REG,0x5A,VXT_END,
-/* 3465 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tcommit,VXT_END,
-/* 3469 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trollback,VXT_END,
-/* 3476 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trestart,VXT_END,
-/* 3483 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3491 */ 2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tstart,VXT_END,
-/* 3499 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_unlock,VXT_END,
-/* 3505 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3513 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_use,VXT_END,
-/* 3517 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_view,
-/* 3525 */ VXT_END,
-/* 3526 */ VXI_CMPL,VXT_VAL,1,VXT_VAL,2,VXT_END,
-/* 3532 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_write,
-/* 3540 */ VXT_END,
-/* 3541 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wteol,
-/* 3549 */ VXT_END,
-/* 3550 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_wtff,VXT_END,
-/* 3556 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wtone,
-/* 3564 */ VXT_END,
-/* 3565 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wttab,
-/* 3573 */ VXT_END,
-/* 3574 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_xkill,
-/* 3582 */ VXT_END,
-/* 3583 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3591 */ SIZEOF(char *) * (short int)xf_xnew,VXT_END,
-/* 3593 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zallocate,
-/* 3601 */ VXT_END,
-/* 3602 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3610 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zattach,VXT_END,
-/* 3614 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3622 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zcompile,VXT_END,
-/* 3626 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3630 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zdeallocate,
-/* 3638 */ VXT_END,
-/* 3639 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3647 */ 1,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_zedit,VXT_END,
-/* 3654 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zg1,VXT_END,
-/* 3661 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHL,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
-/* 3669 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zgoto,VXT_END,
-/* 3677 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zhalt,
-/* 3685 */ VXT_END,
-/* 3686 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3694 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zhelp,VXT_END,
-/* 3698 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3706 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zlink,VXT_END,
-/* 3710 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 3718 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zmess,VXT_END,
-/* 3722 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zprevious,
-/* 3730 */ VXT_END,
-/* 3731 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
-/* 3739 */ 4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3747 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_zprint,VXT_END,
-/* 3755 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,
-/* 3763 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
-/* 3771 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
-/* 3773 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3781 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
-/* 3789 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
-/* 3791 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3799 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3806 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3814 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3821 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3829 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zsystem,VXT_END,
-/* 3833 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_ztcommit,
-/* 3841 */ VXT_END,
-/* 3842 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztstart,VXT_END,
-/* 3848 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_merge,VXT_END,
-/* 3854 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3862 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
-/* 3866 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3874 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
-/* 3878 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,
-/* 3886 */ SIZEOF(char *) * (short int)xf_indmerge,VXT_END,
-/* 3888 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_m_srchindx,
-/* 3896 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 3902 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3910 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzconvert2,VXT_END,
-/* 3917 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3925 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 3933 */ SIZEOF(char *) * (short int)xf_fnzconvert3,VXT_END,
-/* 3935 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3943 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 3951 */ SIZEOF(char *) * (short int)xf_fnzsubstr,VXT_END,
-/* 3953 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3961 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwidth,VXT_END,
-/* 3965 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztrigger,VXT_END,
-/* 3971 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zwritesvn,
-/* 3979 */ VXT_END,
-/* 3980 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3988 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwrite,VXT_END,
-/* 3992 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_igetdst,VXI_MOVL,VXT_REG,0x50,
-/* 4000 */ VXT_ADDR,0,VXT_END,
-/* 4003 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4011 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget1,VXT_END,
-/* 4015 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnpop,
-/* 4023 */ VXT_END,
-/* 4024 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnslot,
-/* 4032 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 4038 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 4046 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indsavglvn,VXT_END,
-/* 4051 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 4059 */ SIZEOF(char *) * (short int)xf_indsavlvn,VXT_END,
-/* 4061 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4069 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshlvn,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 4077 */ VXT_END,
-/* 4078 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 4086 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_savgvn,VXT_END,
-/* 4090 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_savlvn,
-/* 4098 */ VXT_END,
-/* 4099 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4107 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_shareslot,VXT_END,
-/* 4111 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4119 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_stoglvn,VXT_END,
-/* 4123 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4131 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshgvn,VXT_END,
-/* 4135 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 4143 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname2,VXT_END,
-/* 4150 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 4158 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget2,VXT_END,
-/* 4162 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_indmerge2,
-/* 4170 */ VXT_END,
-/* 4171 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 4179 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 4187 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpeek,VXT_END,
-/* 4192 */ 360,374,367,2456,2464,2460,2723,2735,
-/* 4200 */ 2729,0,0,0,481,457,448,0,
-/* 4208 */ 0,444,1965,2003,1984,2604,2619,2610,
-/* 4216 */ 2580,2595,2586,2472,2483,2476,2562,2573,
-/* 4224 */ 2566,2508,2519,2512,2526,2537,2530,2544,
-/* 4232 */ 2555,2548,2490,2501,2494,1944,1958,1951,
-/* 4240 */ 381,395,388};
+/* 3102 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3110 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 3118 */ VXT_END,
+/* 3119 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3127 */ SIZEOF(char *) * (short int)xf_rterror,VXT_END,
+/* 3129 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3137 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setals2als,VXT_END,
+/* 3141 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3149 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsin2alsct,VXT_END,
+/* 3153 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3161 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsctin2als,VXT_END,
+/* 3165 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3173 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsct2alsct,VXT_END,
+/* 3177 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3185 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2als,VXT_END,
+/* 3189 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3197 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2alsct,VXT_END,
+/* 3201 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3209 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3217 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setextract,VXT_END,
+/* 3222 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3230 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3238 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setp1,VXT_END,
+/* 3243 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3251 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3259 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setpiece,VXT_END,
+/* 3267 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3275 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3283 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzextract,VXT_END,
+/* 3288 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3296 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3304 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzp1,VXT_END,
+/* 3309 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3317 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3325 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setzpiece,VXT_END,
+/* 3333 */ VXI_BISB2,VXT_LIT,1,VXT_REG,0x5A,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_dt_true,
+/* 3341 */ VXT_END,
+/* 3342 */ VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3350 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,3,VXI_CALLS,
+/* 3358 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzbrk,VXT_END,
+/* 3363 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 3371 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sorts_after,VXT_END,
+/* 3377 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_srchindx,
+/* 3385 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3391 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
+/* 3399 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
+/* 3405 */ VXI_MOVC3,VXT_LIT,16,VXT_VAL,2,VXT_VAL,1,VXT_END,
+/* 3413 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
+/* 3421 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
+/* 3427 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3435 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_sub,VXT_END,
+/* 3442 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3450 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svget,VXT_END,
+/* 3454 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3462 */ SIZEOF(char *) * (short int)xf_psvput,VXT_END,
+/* 3464 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3472 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svput,VXT_END,
+/* 3476 */ VXI_MOVL,VXT_REG,0x50,VXT_REG,0x5A,VXT_END,
+/* 3482 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tcommit,VXT_END,
+/* 3486 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trollback,VXT_END,
+/* 3493 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trestart,VXT_END,
+/* 3500 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3508 */ 2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tstart,VXT_END,
+/* 3516 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_unlock,VXT_END,
+/* 3522 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3530 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_use,VXT_END,
+/* 3534 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_view,
+/* 3542 */ VXT_END,
+/* 3543 */ VXI_CMPL,VXT_VAL,1,VXT_VAL,2,VXT_END,
+/* 3549 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_write,
+/* 3557 */ VXT_END,
+/* 3558 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wteol,
+/* 3566 */ VXT_END,
+/* 3567 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_wtff,VXT_END,
+/* 3573 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wtone,
+/* 3581 */ VXT_END,
+/* 3582 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wttab,
+/* 3590 */ VXT_END,
+/* 3591 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_xkill,
+/* 3599 */ VXT_END,
+/* 3600 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3608 */ SIZEOF(char *) * (short int)xf_xnew,VXT_END,
+/* 3610 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zallocate,
+/* 3618 */ VXT_END,
+/* 3619 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3627 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zattach,VXT_END,
+/* 3631 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3639 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zcompile,VXT_END,
+/* 3643 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3647 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zdeallocate,
+/* 3655 */ VXT_END,
+/* 3656 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3664 */ 1,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_zedit,VXT_END,
+/* 3671 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zg1,VXT_END,
+/* 3678 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHL,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
+/* 3686 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zgoto,VXT_END,
+/* 3694 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zhalt,
+/* 3702 */ VXT_END,
+/* 3703 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3711 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zhelp,VXT_END,
+/* 3715 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3723 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zlink,VXT_END,
+/* 3727 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 3735 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zmess,VXT_END,
+/* 3739 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zprevious,
+/* 3747 */ VXT_END,
+/* 3748 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
+/* 3756 */ 4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3764 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_zprint,VXT_END,
+/* 3772 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,
+/* 3780 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
+/* 3788 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
+/* 3790 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3798 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
+/* 3806 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
+/* 3808 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3816 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3823 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3831 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3838 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3846 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zsystem,VXT_END,
+/* 3850 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_ztcommit,
+/* 3858 */ VXT_END,
+/* 3859 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztstart,VXT_END,
+/* 3865 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_merge,VXT_END,
+/* 3871 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3879 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
+/* 3883 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3891 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
+/* 3895 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,
+/* 3903 */ SIZEOF(char *) * (short int)xf_indmerge,VXT_END,
+/* 3905 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_m_srchindx,
+/* 3913 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3919 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3927 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzconvert2,VXT_END,
+/* 3934 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3942 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 3950 */ SIZEOF(char *) * (short int)xf_fnzconvert3,VXT_END,
+/* 3952 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3960 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 3968 */ SIZEOF(char *) * (short int)xf_fnzsubstr,VXT_END,
+/* 3970 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3978 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwidth,VXT_END,
+/* 3982 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztrigger,VXT_END,
+/* 3988 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zwritesvn,
+/* 3996 */ VXT_END,
+/* 3997 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4005 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwrite,VXT_END,
+/* 4009 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_igetdst,VXI_MOVL,VXT_REG,0x50,
+/* 4017 */ VXT_ADDR,0,VXT_END,
+/* 4020 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4028 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget1,VXT_END,
+/* 4032 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnpop,
+/* 4040 */ VXT_END,
+/* 4041 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnslot,
+/* 4049 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 4055 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 4063 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indsavglvn,VXT_END,
+/* 4068 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 4076 */ SIZEOF(char *) * (short int)xf_indsavlvn,VXT_END,
+/* 4078 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4086 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshlvn,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 4094 */ VXT_END,
+/* 4095 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 4103 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_savgvn,VXT_END,
+/* 4107 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_savlvn,
+/* 4115 */ VXT_END,
+/* 4116 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4124 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_shareslot,VXT_END,
+/* 4128 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4136 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_stoglvn,VXT_END,
+/* 4140 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4148 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshgvn,VXT_END,
+/* 4152 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 4160 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname2,VXT_END,
+/* 4167 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 4175 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget2,VXT_END,
+/* 4179 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_indmerge2,
+/* 4187 */ VXT_END,
+/* 4188 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 4196 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 4204 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpeek,VXT_END,
+/* 4209 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4217 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsyslog,VXT_END,
+/* 4221 */ 362,376,369,2473,2481,2477,2740,2752,
+/* 4229 */ 2746,0,0,0,483,459,450,0,
+/* 4237 */ 0,446,1982,2020,2001,2621,2636,2627,
+/* 4245 */ 2597,2612,2603,2489,2500,2493,2579,2590,
+/* 4253 */ 2583,2525,2536,2529,2543,2554,2547,2561,
+/* 4261 */ 2572,2565,2507,2518,2511,1961,1975,1968,
+/* 4269 */ 383,397,390};
diff --git a/sr_linux/gtm_env_sp.csh b/sr_linux/gtm_env_sp.csh
index 1aca060..fd4bc67 100644
--- a/sr_linux/gtm_env_sp.csh
+++ b/sr_linux/gtm_env_sp.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2013 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -139,7 +139,7 @@ if ( $?gtm_version_change == "1" ) then
endif
setenv gt_cc_options_common "$gt_cc_options_common -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 "
- setenv gt_cc_options_common "$gt_cc_options_common -D_XOPEN_SOURCE=600 -fsigned-char "
+ setenv gt_cc_options_common "$gt_cc_options_common -D_XOPEN_SOURCE=600 -fsigned-char -Wreturn-type -Wpointer-sign "
if ( "ia64" != $mach_type ) then
if ("$gt_cc_compiler" =~ *icc*) then
@@ -186,7 +186,9 @@ if ( $?gtm_version_change == "1" ) then
setenv gt_cc_option_optimize "-O2 -fno-defer-pop -fno-strict-aliasing -ffloat-store"
if ( "32" == $gt_build_type ) then
# applies to 32bit x86_64, ia32 and cygwin
- setenv gt_cc_option_optimize "$gt_cc_option_optimize -fno-omit-frame-pointer -march=i686"
+ # Compile 32-bit x86 GT.M using 586 instruction set rather than 686 as the new Intel Quark
+ # low power system-on-a-chip uses the 586 instruction set rather than the 686 instruction set
+ setenv gt_cc_option_optimize "$gt_cc_option_optimize -fno-omit-frame-pointer -march=i586"
endif
endif
# -g generate debugging information for dbx (no longer overrides -O)
diff --git a/sr_linux/gtm_env_sp.mk b/sr_linux/gtm_env_sp.mk
deleted file mode 100644
index 81fd6c1..0000000
--- a/sr_linux/gtm_env_sp.mk
+++ /dev/null
@@ -1,182 +0,0 @@
-#################################################################
-# #
-# Copyright 2001, 2012 Fidelity Information Services, Inc #
-# #
-# This source code contains the intellectual property #
-# of its copyright holder(s), and is made available #
-# under a license. If you do not know the terms of #
-# the license, please stop and do not read further. #
-# #
-#################################################################
-
-#
-##########################################################################################
-#
-# gtm_env_sp.mk - environment variable values and aliases specific to Linux
-# if not Linux we assume Cygwin and x86
-#
-##########################################################################################
-# GNU assembler options
-
-gt_as_assembler=as
-gt_as_option_DDEBUG=
-gt_as_option_debug=--gstabs
-gt_as_option_nooptimize=
-gt_as_option_optimize=
-gt_as_options=
-gt_as_options_common=--64
-gt_as_src_suffix=.s
-
-ifeq ($(gt_machine_type), ia64)
-gt_as_assembler=gcc -c
-gt_as_option_debug=
-else
-ifeq ($(gt_machine_type), s390x)
-gt_as_options_common=-march=z9-109 -m64
-gt_as_option_debug=--gdwarf-2
-else
-ifeq ($(gt_machine_type), CYGWIN)
-gt_as_option_debug=--gdwarf-2
-gt_as_options_common=--defsym cygwin=1
-endif
-endif
-endif
-ifeq ($(gt_build_type), 32)
-ifeq ($(gt_os_type),Linux)
-gt_as_options_common=--32
-endif
-endif
-
-# C compiler options
-
-gt_cc_shl_fpic=-fPIC
-gt_cc_options_common=-c -ansi
-ifeq ($(gt_os_type),CYGWIN)
-gt_cc_option_debug=$(gt_cc_option_debug) -gdwarf-2 -fno-inline -fno-inline-functions
-gt_cc_shl_fpic=
-gt_cc_options_common=-c
-endif
-
-gt_cc_compiler=cc
-gt_cc_option_DBTABLD=-DNOLIBGTMSHR
-gt_cc_option_DDEBUG=-DDEBUG
-gt_cc_option_debug=-g
-gt_cc_option_nooptimize=
-gt_cc_option_optimize=-O2 -fno-defer-pop -fno-strict-aliasing -ffloat-store
-gt_cc_options_common+= -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=600 -fsigned-char
-
-ifeq ($(gt_machine_type), x86_64)
-ifeq ($(gt_build_type),32)
-# The /emul/ia32-linux/... directory doesn't exist on most machines, but when it's there we need it. No problem
-# with always includeing it.
-gt_cc_option_I+= -I/emul/ia32-linux/usr/include/
-else
-gt_cc_option_I=
-endif
-endif
-
-# autodepend option
-gt_cc_dep_option=-w
-
-ifeq ($(gt_machine_type), ia64)
-gt_cc_option_optimize=-O
-else
-gt_cc_options_common+= $(gt_cc_shl_fpic) -Wmissing-prototypes -D_LARGEFILE64_SOURCE
-ifeq ($(gt_build_type),32)
-gt_cc_option_optimize+= -march=i686
-endif
-endif
-
-gt_cc_shl_options=-c $(gt_cc_shl_fpic)
-
-ifeq ($(gt_os_type),CYGWIN)
-gt_cc_options_common+= -DNO_SEM_TIME -DNO_SEM_GETPID
-endif
-
-# Linker definitions:
-
-gt_ld_aio_syslib=
-gt_ld_ci_options=-Wl,-u,gtm_ci -Wl,-u,gtm_filename_to_id -Wl,--version-script,gtmshr_symbols.export
-gt_ld_ci_u_option=-Wl,-u,gtm_ci
-gt_ld_linker=$(gt_cc_compiler)
-gt_ld_m_shl_linker=ld
-gt_ld_m_shl_options=-shared
-gt_ld_option_output=-o
-gt_ld_options_all_exe=-rdynamic -Wl,-u,gtm_filename_to_id -Wl,-u,gtm_zstatus -Wl,--version-script,gtmexe_symbols.export
-gt_ld_options_bta=-Wl,-M
-gt_ld_options_common=-Wl,-M
-gt_ld_options_dbg=-Wl,-M
-gt_ld_options_gtmshr=-Wl,-u,gtm_filename_to_id -Wl,--version-script,gtmshr_symbols.export
-gt_ld_options_pro=-Wl,-M
-gt_ld_shl_linker=cc
-gt_ld_shl_options=-shared
-gt_ld_shl_suffix=.so
-gt_ld_sysrtns=
-
-ifeq ($(gt_build_type),32)
-gt_ld_m_shl_options=
-endif
-
-# -lrt for async I/O in mupip recover/rollback
-# -lrt doesn't work to pull in semaphores with GCC 4.6, so use -lpthread.
-# Add -lc in front of -lpthread to avoid linking in thread-safe versions
-# of libc routines from libpthread.
-ifeq ($(gt_build_type), 64)
-gt_ld_syslibs=-lrt -lelf -lncurses -lm -ldl -lc -lpthread
-else
-ifeq ($(gt_os_type),Linux)
-gt_ld_syslibs=-lrt -lncurses -lm -ldl -lc -lpthread
-else
-gt_ld_syslibs=-lncurses -lm -lcrypt
-endif
-endif
-
-# lint definition overrides
-gt_lint_linter=
-gt_lint_options_library=-x
-gt_lint_options_common=
-
-gt_cpus=$(shell grep -c process /proc/cpuinfo)
-# used to build VPATH
-# Apparently Ubuntu does not like the -e option for echo, delete this if the *.mdep make files generate an error
-ifeq ($(distro),ubuntu)
-gt_echoe=echo
-else
-gt_echoe=echo -e
-endif
-
-ifeq ($(gt_build_type), 32)
-gt_cc_options_common+=-m32
-gt_ld_options_gtmshr+=-m32
-gt_cc_shl_options+=-m32
-gt_ld_options_common+=-m32
-endif
-#
-# gas assembly - the preprocessor works
-#
-define gt-as
-$(gt_as_assembler) $(gt_as_options) $< -o $@
-endef
-define gt_cpp
-$(gt_cpp_compiler) -E $(gt_cpp_options_common) $(gt_cc_option_I) $< > $<_cpp.s
-endef
-define gt-as_cpp
-$(gt_as_assembler) $(gt_as_options) $<_cpp.s -o $@
-endef
-#
-# gcc specific rule to get the depend file (CC -M)
-#
-define gt-dep
- @echo $*.o $*.d : '\' > $@; \
- echo $(notdir $(filter-out /usr/include% /usr/lib% /usr/local/include% /usr/local/lib/%, \
- $(filter %.c %.h,$(shell $(gt_cc_compiler) -M $(gt_cc_options) $(gt_cc_dep_option) $<)))) >> $@
-endef
-define gt-export
- @echo "{" >$@
- @echo "global:" >>$@
- @sed 's/\(.*\)/ \1;/g' $< >>$@
- @echo "local:" >>$@
- @echo " *;" >>$@
- @echo "};" >>$@
-endef
-
diff --git a/sr_linux/gtm_getenv.c b/sr_linux/gtm_getenv.c
index b75c8e4..689b057 100644
--- a/sr_linux/gtm_getenv.c
+++ b/sr_linux/gtm_getenv.c
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2007 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2007, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#ifdef __CYGWIN__
diff --git a/sr_linux/platform.cmake b/sr_linux/platform.cmake
index 4e8605f..60538a5 100644
--- a/sr_linux/platform.cmake
+++ b/sr_linux/platform.cmake
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2013 Fidelity Information Services, Inc #
+# Copyright 2013, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -13,6 +13,9 @@ if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4)
set(arch "x86")
set(bits 32)
set(FIND_LIBRARY_USE_LIB64_PATHS FALSE)
+ # Set arch to i586 in order to compile for Galileo
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i586")
+ set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-march=i586")
else()
set(arch "x86_64")
set(bits 64)
@@ -32,7 +35,7 @@ set(CMAKE_INCLUDE_FLAG_ASM "-Wa,-I") # gcc -I does not make it to "as"
# Compiler
set(CMAKE_C_FLAGS
- "${CMAKE_C_FLAGS} -ansi -fsigned-char -fPIC -Wmissing-prototypes -fno-omit-frame-pointer")
+ "${CMAKE_C_FLAGS} -ansi -fsigned-char -fPIC -Wmissing-prototypes -Wreturn-type -Wpointer-sign -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS_RELEASE
"${CMAKE_C_FLAGS_RELEASE} -fno-defer-pop -fno-strict-aliasing -ffloat-store")
diff --git a/sr_linux/release_name.h b/sr_linux/release_name.h
index 099559d..d67cbe3 100644
--- a/sr_linux/release_name.h
+++ b/sr_linux/release_name.h
@@ -10,15 +10,15 @@
****************************************************************/
#ifdef __CYGWIN__
-#define GTM_RELEASE_NAME "GT.M V6.1-000 CYGWIN x86"
+#define GTM_RELEASE_NAME "GT.M V6.2-000 CYGWIN x86"
#elif defined(__ia64)
-#define GTM_RELEASE_NAME "GT.M V6.1-000 Linux IA64"
+#define GTM_RELEASE_NAME "GT.M V6.2-000 Linux IA64"
#elif defined(__x86_64__)
-#define GTM_RELEASE_NAME "GT.M V6.1-000 Linux x86_64"
+#define GTM_RELEASE_NAME "GT.M V6.2-000 Linux x86_64"
#elif defined(__s390__)
-#define GTM_RELEASE_NAME "GT.M V6.1-000 Linux S390X"
+#define GTM_RELEASE_NAME "GT.M V6.2-000 Linux S390X"
#else
-#define GTM_RELEASE_NAME "GT.M V6.1-000 Linux x86"
+#define GTM_RELEASE_NAME "GT.M V6.2-000 Linux x86"
#endif
#define GTM_PRODUCT "GT.M"
-#define GTM_VERSION "V6.1"
+#define GTM_VERSION "V6.2"
diff --git a/sr_port/advancewindow.c b/sr_port/advancewindow.c
index 6329e7c..39b12d0 100644
--- a/sr_port/advancewindow.c
+++ b/sr_port/advancewindow.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -51,12 +51,12 @@ static readonly unsigned char apos_ok[] =
void advancewindow(void)
{
- unsigned char *cp1, *cp2, *cp3, x;
+ unsigned char *cp1, *cp2, *cp3, *cptr;
+ unsigned char *error, errtxt[(3 + 1) UNICODE_ONLY(* GTM_MB_LEN_MAX)], x; /* up to 3 digits/byte & a comma */
char *tmp;
int y, charlen;
# ifdef UNICODE_SUPPORTED
uint4 ch;
- unsigned char *cptr;
# endif
DCL_THREADGBL_ACCESS;
@@ -97,7 +97,22 @@ void advancewindow(void)
if (!run_time)
{
show_source_line(TRUE);
- dec_err(VARLSTCNT(1) ERR_LITNONGRAPH);
+ if (!gtm_utf8_mode)
+ charlen = 1; /* always one character in M mode */
+# ifdef UNICODE_SUPPORTED
+ else
+ {
+ charlen = cptr - cp1 + 1; /* get the number of bytes in the utf8 character */
+ assert(GTM_MB_LEN_MAX >= charlen);
+ }
+# endif
+ for (cptr = cp1 - 1; charlen--;) /* stop when all bytes are done */
+ { /* cptr winds up back where it started due to the increments in the loop */
+ error = (unsigned char*)i2asc((uchar_ptr_t)errtxt, (unsigned int)*cptr++);
+ *error++ = ',';
+ }
+ error--; /* do not include the last comma */
+ dec_err(VARLSTCNT(4) ERR_LITNONGRAPH, 2, (error - errtxt), errtxt);
}
}
if ('\"' == x)
diff --git a/sr_port/alias.h b/sr_port/alias.h
index 0a56ef7..329d5ff 100644
--- a/sr_port/alias.h
+++ b/sr_port/alias.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -15,21 +15,21 @@
#define DOLLAR_ZWRTAC "$ZWRTAC"
/* Min and max for the number of stringpool garbage collections (SPGC) that will be done without having
- done a lv_val garbage collection (aka LVGC aka als_lvval_gc). While I did give these numbers some
- thought, they aren't far from semi-random. Since the LVGC is kind of expensive (requiring two
- traversals of the lv_vals in a symbol table) I decided 2 SPGCs was good to spread the cost of one
- LVGC over. For the max, I didn't want to let it get too high so the tuning algorithm didn't take a
- long time to get back to a more frequent value when necessary yet 64 seems fairly infrequent.
- These numbers are totally subject to future studies.. [SE 12/2008]
-*/
+ * done a lv_val garbage collection (aka LVGC aka als_lvval_gc). While I did give these numbers some
+ * thought, they aren't far from semi-random. Since the LVGC is kind of expensive (requiring two
+ * traversals of the lv_vals in a symbol table) I decided 2 SPGCs was good to spread the cost of one
+ * LVGC over. For the max, I didn't want to let it get too high so the tuning algorithm didn't take a
+ * long time to get back to a more frequent value when necessary yet 64 seems fairly infrequent.
+ * These numbers are totally subject to future studies.. [SE 12/2008]
+ */
#define MIN_SPGC_PER_LVGC 2
#define MAX_SPGC_PER_LVGC 64
#include "zwrite.h"
/* Macro used intermittently in code to debug alias code in general. Note this macro must be specified
- as a compile option since it is used in macros that do not pull in this alias.h header file.
-*/
+ * as a compile option since it is used in macros that do not pull in this alias.h header file.
+ */
#ifdef DEBUG_ALIAS
# define DBGALS(x) DBGFPF(x)
# define DBGALS_ONLY(x) x
@@ -48,124 +48,122 @@
# define DBGRFCT_ONLY(x)
#endif
-/* Since DBGFPF calls flush_pio, if we are debugging, include the defining header file */
+/* Since DBGFPF calls flush_pio, if we are debugging, include the defining header file - and they need stack frame */
#if defined(DEBUG_ALIAS) || defined(DEBUG_REFCNT)
# include "io.h"
+# include "stack_frame.h"
#endif
/* Macro to increment total refcount (and optionally trace it) */
-#define INCR_TREFCNT(lv) \
-{ \
- assert(LV_IS_BASE_VAR(lv)); \
- DBGRFCT((stderr, "\nIncrement trefcnt for lv_val at 0x"lvaddr" from %d to %d by %s line %d\n", \
- (lv), (lv)->stats.trefcnt, (lv)->stats.trefcnt + 1, __FILE__, __LINE__)); \
- ++(lv)->stats.trefcnt; \
+#define INCR_TREFCNT(lv) \
+{ \
+ GBLREF stack_frame *frame_pointer; \
+ \
+ assert(LV_IS_BASE_VAR(lv)); \
+ DBGRFCT((stderr, "\nIncrement trefcnt for lv_val at 0x"lvaddr" from %d to %d by %s line %d at mpc 0x"lvaddr"\n", \
+ (lv), (lv)->stats.trefcnt, (lv)->stats.trefcnt + 1, __FILE__, __LINE__, frame_pointer->mpc)); \
+ ++(lv)->stats.trefcnt; \
+ assert(0 < (lv)->stats.trefcnt); \
+ assert((lv)->stats.trefcnt > (lv)->stats.crefcnt); \
}
/* Macro to decrement total refcount (and optionally trace it) */
-#define DECR_TREFCNT(lv) \
-{ \
- assert(LV_IS_BASE_VAR(lv)); \
- DBGRFCT((stderr, "\nDecrement trefcnt for lv_val at 0x"lvaddr" from %d to %d by %s line %d\n", \
- (lv), (lv)->stats.trefcnt, (lv)->stats.trefcnt - 1, __FILE__, __LINE__)); \
- --(lv)->stats.trefcnt; \
- assert(0 <= (lv)->stats.trefcnt); \
+#define DECR_TREFCNT(lv) \
+{ \
+ GBLREF stack_frame *frame_pointer; \
+ \
+ assert(LV_IS_BASE_VAR(lv)); \
+ DBGRFCT((stderr, "\nDecrement trefcnt for lv_val at 0x"lvaddr" from %d to %d by %s line %d at mpc 0x"lvaddr"\n", \
+ (lv), (lv)->stats.trefcnt, (lv)->stats.trefcnt - 1, __FILE__, __LINE__, frame_pointer->mpc)); \
+ assert((lv)->stats.trefcnt > (lv)->stats.crefcnt); \
+ --(lv)->stats.trefcnt; \
+ assert(0 <= (lv)->stats.trefcnt); \
}
/* Macro to increment container refcount (and optionally trace it) */
-#define INCR_CREFCNT(lv) \
-{ \
- assert(LV_IS_BASE_VAR(lv)); \
- DBGRFCT((stderr, "\nIncrement crefcnt for lv_val at 0x"lvaddr" from %d to %d by %s line %d\n", \
- (lv), (lv)->stats.crefcnt, (lv)->stats.crefcnt + 1, __FILE__, __LINE__)); \
- ++(lv)->stats.crefcnt; \
+#define INCR_CREFCNT(lv) \
+{ \
+ GBLREF stack_frame *frame_pointer; \
+ \
+ assert(LV_IS_BASE_VAR(lv)); \
+ DBGRFCT((stderr, "\nIncrement crefcnt for lv_val at 0x"lvaddr" from %d to %d by %s line %d at mpc 0x"lvaddr"\n", \
+ (lv), (lv)->stats.crefcnt, (lv)->stats.crefcnt + 1, __FILE__, __LINE__, frame_pointer->mpc)); \
+ assert((lv)->stats.trefcnt > (lv)->stats.crefcnt); \
+ ++(lv)->stats.crefcnt; \
+ assert(0 < (lv)->stats.crefcnt); \
}
/* Macro to decrement container refcount (and optionally trace it) */
-#define DECR_CREFCNT(lv) \
-{ \
- assert(LV_IS_BASE_VAR(lv)); \
- DBGRFCT((stderr, "\nDecrement crefcnt for lv_val at 0x"lvaddr" from %d to %d by %s line %d\n", \
- (lv), (lv)->stats.crefcnt, (lv)->stats.crefcnt - 1, __FILE__, __LINE__)); \
- --(lv)->stats.crefcnt; \
- assert(0 <= (lv)->stats.crefcnt); \
+#define DECR_CREFCNT(lv) \
+{ \
+ GBLREF stack_frame *frame_pointer; \
+ \
+ assert(LV_IS_BASE_VAR(lv)); \
+ DBGRFCT((stderr, "\nDecrement crefcnt for lv_val at 0x"lvaddr" from %d to %d by %s line %d at mpc 0x"lvaddr"\n", \
+ (lv), (lv)->stats.crefcnt, (lv)->stats.crefcnt - 1, __FILE__, __LINE__, frame_pointer->mpc)); \
+ --(lv)->stats.crefcnt; \
+ assert(0 <= (lv)->stats.crefcnt); \
+ assert((lv)->stats.trefcnt > (lv)->stats.crefcnt); \
}
-/* There are three flavors of DECR_BASE_REF depending on the activities we need to persue. The first two flavors
- DECR_BASE_REF and DECR_BASE_REF_RQ take 2 parms (hashtable entry and lv_val addresses). Both of these do hashtable
- entry maint in addition to lv_val maint but do it in different ways. The DECR_BASE_REF macro's purpose is to
- leave the hashtable always pointing to a valid lv_val. If the one we are decrementing goes to zero, we can just
- zap that one and leave it there but if the refcnt is not zero, we can't do that. Since another command may
- follow the command doing the DECR_BASE_REF (e.g. KILL *), we can't leave the hash table entry with a null value
- since gtm_fetch() won't be called to fill it in so we must allocate a new lv_val for it. By contrast, with the
- DECR_BASE_REF_RQ macro, if the lv_val refcnt goes to zero, the lv_val is requeued and in either case, the hte
- address is cleared to make way for a new value. The 3rd flavor is the DCR_BASE_REF_NOSYM macro which is used for
- orphaned lv_vals not in a hashtable. This macro just requeues lv_vals that hit a refcnt of zero.
-*/
-
-#define LVP_KILL_SUBTREE_IF_EXISTS(lvp, dotpsave) \
-{ \
- lvTree *lvt_child; \
- \
- assert(LV_IS_BASE_VAR(lvp)); \
- assert(0 == (lvp)->stats.crefcnt); \
- lvt_child = LV_GET_CHILD(lvp); \
- if (NULL != lvt_child) \
- { \
- assert(((lvTreeNode *)(lvp)) == LVT_PARENT(lvt_child)); \
- LV_CHILD(lvp) = NULL; \
- lv_killarray(lvt_child, dotpsave); \
- } \
-}
+/* There are three flavors of DECR_BASE_REF depending on the activities we need to pursue. The first two flavors
+ * DECR_BASE_REF and DECR_BASE_REF_RQ take 3 parms (hashtable entry and lv_val addresses) plus dotpsave which controls
+ * whether lv_val gets TP-cloned or not. Both of these do hashtable entry maint in addition to lv_val maint but do it
+ * in different ways. The DECR_BASE_REF macro's purpose is to leave the hashtable always pointing to a valid lv_val.
+ * If the one we are decrementing goes to zero, we can just zap that one and leave it there but if the refcnt is not
+ * zero, we can't do that. Since another command may follow the command doing the DECR_BASE_REF (e.g. KILL *), we can't
+ * leave the hash table entry with a null value since gtm_fetch() won't be called to fill it in so we must allocate a
+ * new lv_val for it. By contrast, with the DECR_BASE_REF_RQ macro, if the lv_val refcnt goes to zero, the lv_val is
+ * requeued and in either case, the hte address is cleared to make way for a new value. The 3rd flavor is the
+ * DECR_BASE_REF_NOSYM macro which is used for orphaned lv_vals not in a hashtable. This macro just puts lv_vals
+ * that hit a refcnt of zero back on the freelist.
+ */
/* Macro to decrement a base var reference and do appropriate cleanup */
-#define DECR_BASE_REF(tabent, lvp, dotpsave) \
-{ /* Perform reference count maintenance for base var */ \
- lv_val *dbr_lvp; \
- symval *sym; \
- \
- assert(LV_IS_BASE_VAR(lvp)); \
- assert(0 < (lvp)->stats.trefcnt); \
- DECR_TREFCNT(lvp); \
- sym = LV_GET_SYMVAL(lvp); \
- if (0 == (lvp)->stats.trefcnt) \
- { /* This lv_val can be effectively killed and remain in hte */ \
- LVP_KILL_SUBTREE_IF_EXISTS(lvp, dotpsave); \
- assert(NULL == (lvp)->tp_var); \
- LVVAL_INIT(lvp, sym); \
- } else \
- { /* lv_val otherwise still in use -- put a new one in this hte */ \
- assert((lvp)->stats.trefcnt >= (lvp)->stats.crefcnt); \
- dbr_lvp = lv_getslot(sym); \
- DBGRFCT((stderr, "DECR_BASE_REF: Resetting hte 0x"lvaddr" from 0x"lvaddr" to 0x"lvaddr"\n", \
- tabent, (lvp), dbr_lvp)); \
- LVVAL_INIT(dbr_lvp, sym); \
- tabent->value = dbr_lvp; \
- } \
+#define DECR_BASE_REF(tabent, lvp, dotpsave) \
+{ /* Perform reference count maintenance for base var */ \
+ GBLREF stack_frame *frame_pointer; \
+ lv_val *dbr_lvp; \
+ symval *sym; \
+ \
+ assert(LV_IS_BASE_VAR(lvp)); \
+ assert(0 < (lvp)->stats.trefcnt); \
+ DECR_TREFCNT(lvp); \
+ sym = LV_GET_SYMVAL(lvp); \
+ if (0 == (lvp)->stats.trefcnt) \
+ { /* This lv_val can be effectively killed and remain in hte */ \
+ LVP_KILL_SUBTREE_IF_EXISTS(lvp, dotpsave); \
+ assert(NULL == (lvp)->tp_var); \
+ LVVAL_INIT(lvp, sym); \
+ } else \
+ { /* lv_val otherwise still in use -- put a new one in this hte */ \
+ assert((lvp)->stats.trefcnt >= (lvp)->stats.crefcnt); \
+ dbr_lvp = lv_getslot(sym); \
+ DBGRFCT((stderr, "DECR_BASE_REF: Resetting hte 0x"lvaddr" (var %.*s) from 0x"lvaddr" to 0x"lvaddr" at mpc: 0x" \
+ lvaddr" in %s at line %d\n", tabent, tabent->key.var_name.len, tabent->key.var_name.addr, (lvp), \
+ dbr_lvp, frame_pointer->mpc, __FILE__, __LINE__)); \
+ LVVAL_INIT(dbr_lvp, sym); \
+ tabent->value = dbr_lvp; \
+ } \
}
/* Macro to decrement a base var reference and do appropriate cleanup except the tabent value is unconditionally
* cleared and the lvval put on the free queue. Used when the tabent is about to be reused for a different lv.
*/
-#define DECR_BASE_REF_RQ(tabent, lvp, dotpsave) \
-{ /* Perform reference count maintenance for base var */ \
- assert(LV_IS_BASE_VAR(lvp)); \
- assert(0 < (lvp)->stats.trefcnt); \
- DECR_TREFCNT(lvp); \
- DBGRFCT((stderr, "DECR_BASE_REF_RQ: Resetting hte 0x"lvaddr" from 0x"lvaddr" to NULL\n", \
- tabent, tabent->value)); \
- tabent->value = (void *)NULL; \
- if (0 == (lvp)->stats.trefcnt) \
- { /* This lv_val is done .. requeue it after it is killed */ \
- LVP_KILL_SUBTREE_IF_EXISTS(lvp, dotpsave); \
- LV_FREESLOT(lvp); \
- } else \
- assert((lvp)->stats.trefcnt >= (lvp)->stats.crefcnt); \
+#define DECR_BASE_REF_RQ(tabent, lvp, dotpsave) \
+{ /* Perform reference count maintenance for base var */ \
+ GBLREF stack_frame *frame_pointer; \
+ \
+ DBGRFCT((stderr, "DECR_BASE_REF_RQ: Resetting hte 0x"lvaddr" (var %.*s) from 0x"lvaddr" to NULL for mpc 0x"lvaddr \
+ " in %s at line %d\n", tabent, tabent->key.var_name.len, tabent->key.var_name.addr, tabent->value, \
+ frame_pointer->mpc, __FILE__, __LINE__)); \
+ tabent->value = (void *)NULL; \
+ DECR_BASE_REF_NOSYM(lvp, dotpsave); \
}
-/* Macro to decrement a base var reference and do appropriate cleanup except no hash table
- entry value cleanup is done.
-*/
+/* Macro to decrement a base var reference and do appropriate cleanup (if any) but no hash table
+ * entry value cleanup is done like is done in the other DECR_BASE_REF* flavors.
+ */
#define DECR_BASE_REF_NOSYM(lvp, dotpsave) \
{ /* Perform reference count maintenance for base var */ \
assert(LV_IS_BASE_VAR(lvp)); \
@@ -173,34 +171,55 @@
DECR_TREFCNT(lvp); \
if (0 == (lvp)->stats.trefcnt) \
{ /* This lv_val is done .. requeue it after it is killed */ \
+ assert(0 == (lvp)->stats.crefcnt); \
LVP_KILL_SUBTREE_IF_EXISTS(lvp, dotpsave); \
LV_FREESLOT(lvp); \
} else \
assert((lvp)->stats.trefcnt >= (lvp)->stats.crefcnt); \
}
+#define LVP_KILL_SUBTREE_IF_EXISTS(lvp, dotpsave) \
+{ \
+ lvTree *lvt_child; \
+ \
+ assert(LV_IS_BASE_VAR(lvp)); \
+ assert(0 == (lvp)->stats.crefcnt); \
+ lvt_child = LV_GET_CHILD(lvp); \
+ if (NULL != lvt_child) \
+ { \
+ assert(((lvTreeNode *)(lvp)) == LVT_PARENT(lvt_child)); \
+ LV_CHILD(lvp) = NULL; \
+ DBGRFCT((stderr, "\nLVP_KILL_SUBTREE_IF_EXISTS: Base lv 0x"lvaddr" being killed has subtree 0x"lvaddr \
+ " that also needs killing - drive lv_killarray on it at %s at line %d\n", (lvp), lvt_child, \
+ __FILE__, __LINE__)); \
+ lv_killarray(lvt_child, dotpsave); \
+ } \
+}
+
/* Macro to decrement an alias container reference and do appropriate cleanup */
-#define DECR_AC_REF(lvp, dotpsave) \
-{ \
- if (MV_ALIASCONT & (lvp)->v.mvtype) \
- { /* Killing an alias container, perform reference count maintenance */ \
- \
- GBLREF uint4 dollar_tlevel; \
- \
- lv_val *lvref = (lv_val *)(lvp)->v.str.addr; \
- assert(0 == (lvp)->v.str.len); \
- assert(!LV_IS_BASE_VAR(lvp)); \
- assert(lvref); \
- assert(LV_IS_BASE_VAR(lvref)); \
- assert(0 < lvref->stats.crefcnt); \
- assert(0 < lvref->stats.trefcnt); \
- if (dotpsave && dollar_tlevel && (NULL != lvref->tp_var) \
- && !lvref->tp_var->var_cloned && (1 == lvref->stats.trefcnt)) \
- /* Only clone (here) if target is going to be deleted by decrement */ \
- TP_VAR_CLONE(lvref); \
- DECR_CREFCNT(lvref); \
- DECR_BASE_REF_NOSYM(lvref, dotpsave); \
- } \
+#define DECR_AC_REF(lvp, dotpsave) \
+{ \
+ if (MV_ALIASCONT & (lvp)->v.mvtype) \
+ { /* Killing an alias container, perform reference count maintenance */ \
+ \
+ GBLREF uint4 dollar_tlevel; \
+ \
+ lv_val *lvref = (lv_val *)(lvp)->v.str.addr; \
+ assert(0 == (lvp)->v.str.len); \
+ assert(!LV_IS_BASE_VAR(lvp)); \
+ assert(lvref); \
+ assert(LV_IS_BASE_VAR(lvref)); \
+ assert(0 < lvref->stats.crefcnt); \
+ assert(0 < lvref->stats.trefcnt); \
+ DBGRFCT((stderr, "\nDECR_AC_REF: Killing alias container 0x"lvaddr" pointing to lv_val 0x"lvaddr"\n", \
+ lvp, lvref)); \
+ if (dotpsave && dollar_tlevel && (NULL != lvref->tp_var) \
+ && !lvref->tp_var->var_cloned && (1 == lvref->stats.trefcnt)) \
+ /* Only clone (here) if target is going to be deleted by decrement */ \
+ TP_VAR_CLONE(lvref); \
+ DECR_CREFCNT(lvref); \
+ DECR_BASE_REF_NOSYM(lvref, dotpsave); \
+ } \
}
/* Macro to mark nested symvals as having had alias activity. Mark nested symvals until we get
@@ -228,60 +247,31 @@
* by setting it up to be cloned if deleted. This activity should nest so container vars that point to further trees should also
* be scanned.
*/
-#define TPSAV_CNTNRS_IN_TREE(lv_base) \
-{ \
- lvTree *lvt; \
- \
- assert(LV_IS_BASE_VAR(lv_base)); \
- if (lv_base->stats.tstartcycle != tstartcycle) \
- { /* If haven't processed this lv_val for this transaction (or nested transaction */ \
- lv_base->stats.tstartcycle = tstartcycle; \
- /* Note it is possible that this lv_val has the current tstart cycle if there has been a restart. We still need \
- to rescan the var anyway since one attempt can execute differently than a following attempt and thus create \
- different variables for us to find -- if it has aliases in it that is. \
- */ \
- if ((NULL != (lvt = LV_GET_CHILD(lv_base))) PRO_ONLY(&& (lv_base)->has_aliascont)) \
- { \
- DBGRFCT((stderr, "\n## TPSAV_CNTNRS_IN_TREE: Beginning processing lvTree at 0x"lvaddr"\n", lv_base)); \
- als_prcs_tpsav_cntnr(lvt); \
- DBGRFCT((stderr, "\n## TPSAV_CNTNRS_IN_TREE: Finished processing lvTree at 0x"lvaddr"\n", lv_base)); \
- } \
- } else \
- DBGRFCT((stderr, "\n## TPSAV_CNTNRS_IN_TREE: Bypassing lvTree at 0x"lvaddr" as already processed\n", lv_base)); \
-}
-
-/* Macro similar to TPSAV_CNTNRS_IN_TREE() above but in this case, we know we want to increment the reference counts
- * for all found container var targets. They have already been saved (we will assert they have a tp_var!) and we just want to
- * reestablish the reference counts. This is used when a saved array is being restored and the containers in it need to have
- * their reference counts re-established.
- */
-#define TPREST_CNTNRS_IN_TREE(lv_base) \
-{ \
- lvTree *lvt; \
- \
- assert(LV_IS_BASE_VAR(lv_base)); \
- if ((NULL != (lvt = LV_GET_CHILD(lv_base))) PRO_ONLY(&& (lv_base)->has_aliascont)) \
- { \
- DBGRFCT((stderr, "\n++ TPREST_CNTNRS_IN_TREE: Beginning processing lvTree at 0x"lvaddr"\n", lv_base)); \
- als_prcs_tprest_cntnr(lvt); \
- DBGRFCT((stderr, "\n++ TPREST_CNTNRS_IN_TREE: Finished processing lvTree at 0x"lvaddr"\n", lv_base)); \
- } \
-}
-
-/* Macro similar to TPREST_CNTNRS_IN_TREE() above but in this case we want to decrement the containers since we are
- in unwind processing */
-#define TPUNWND_CNTNRS_IN_TREE(lv_base) \
-{ \
- lvTree *lvt; \
- \
- assert(LV_IS_BASE_VAR(lv_base)); \
- if ((NULL != (lvt = LV_GET_CHILD(lv_base))) PRO_ONLY(&& (lv_base)->has_aliascont)) \
- { \
- DBGRFCT((stderr, "\n-- TPUNWND_CNTNRS_IN_TREE: Beginning processing lvTree at 0x"lvaddr"\n", lv_base)); \
- als_prcs_tpunwnd_cntnr(lvt); \
- DBGRFCT((stderr, "\n-- TPUNWND_CNTNRS_IN_TREE: Finished processing lvTree at 0x"lvaddr"\n", lv_base)); \
- } else \
- DBGRFCT((stderr, "\n-- TPUNWND_CNTNRS_IN_TREE: Scan for lvTree at 0x"lvaddr" bypassed - no containers", lv_base));\
+#define TPSAV_CNTNRS_IN_TREE(lv_base) \
+{ \
+ GBLREF stack_frame *frame_pointer; \
+ lvTree *lvt; \
+ \
+ assert(LV_IS_BASE_VAR(lv_base)); \
+ if (lv_base->stats.tstartcycle != tstartcycle) \
+ { /* If haven't processed this lv_val for this transaction (or nested transaction) */ \
+ DBGRFCT((stderr, "\nTPSAV_CNTNRS_IN_TREE: Entered for lv 0x"lvaddr" - tstartcycle: %d lvtstartcycle: %d in %s " \
+ "at line %d\n", lv_base, tstartcycle, lv_base->stats.tstartcycle, __FILE__, __LINE__)); \
+ lv_base->stats.tstartcycle = tstartcycle; \
+ /* Note it is possible that this lv_val has the current tstart cycle if there has been a restart. We still need \
+ * to rescan the var anyway since one attempt can execute differently than a following attempt and thus create \
+ * different variables for us to find -- if it has aliases in it that is. \
+ */ \
+ if ((NULL != (lvt = LV_GET_CHILD(lv_base))) PRO_ONLY(&& (lv_base)->has_aliascont)) \
+ { \
+ DBGRFCT((stderr, "\n## TPSAV_CNTNRS_IN_TREE: Beginning processing lv_base at 0x"lvaddr" for mpc" \
+ " 0x"lvaddr" in %s at line %d\n", lv_base, frame_pointer->mpc, __FILE__, __LINE__)); \
+ als_prcs_tpsav_cntnr(lvt); \
+ DBGRFCT((stderr, "\n## TPSAV_CNTNRS_IN_TREE: Finished processing lv_base at 0x"lvaddr"\n", lv_base)); \
+ } \
+ } else \
+ DBGRFCT((stderr, "\n## TPSAV_CNTNRS_IN_TREE: Bypassing lv_base at 0x"lvaddr" as already processed in %s at line" \
+ "%d\n", lv_base, __FILE__, __LINE__)); \
}
/* Macro to scan a tree for container vars, delete what they point to and unmark the container so it is no longer a container */
@@ -311,6 +301,28 @@
lv_base->has_aliascont = TRUE; \
}
+#define CLEAR_ALIAS_RETARG \
+{ /* An error/restart has occurred while an alias return arg was in-flight. Return won't happen \
+ * now so we need to remove the extra counts that were added in unw_retarg() and dis-enchant \
+ * the alias container itself. \
+ */ \
+ lv_val *lvptr; \
+ \
+ GBLREF mval *alias_retarg; \
+ \
+ assert(NULL != alias_retarg); \
+ assert(alias_retarg->mvtype & MV_ALIASCONT); \
+ if (alias_retarg->mvtype & MV_ALIASCONT) \
+ { /* Protect the refs were are about to make in case ptr got banged up somehow */ \
+ lvptr = (lv_val *)alias_retarg->str.addr; \
+ assert(LV_IS_BASE_VAR(lvptr)); \
+ DECR_CREFCNT(lvptr); \
+ DECR_BASE_REF_NOSYM(lvptr, FALSE); \
+ } \
+ alias_retarg->mvtype = 0; /* Kill the temp var (no longer a container) */ \
+ alias_retarg = NULL; /* And no more in-flight return argument */ \
+}
+
void als_lsymtab_repair(hash_table_mname *table, ht_ent_mname *table_base_orig, int table_size_orig);
void als_check_xnew_var_aliases(symval *oldsymtab, symval *cursymtab);
void als_zwrhtab_init(void);
diff --git a/sr_port/alias_funcs.c b/sr_port/alias_funcs.c
index 1c099a3..13b39b5 100644
--- a/sr_port/alias_funcs.c
+++ b/sr_port/alias_funcs.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -53,8 +53,6 @@ GBLREF zwr_hash_table *zwrhtab;
GBLREF trans_num local_tn; /* transaction number for THIS PROCESS */
GBLREF uint4 tstartcycle;
GBLREF uint4 lvtaskcycle; /* lv_val cycle for misc lv_val related tasks */
-GBLREF mstr **stp_array;
-GBLREF int stp_array_size;
GBLREF lv_val *zsrch_var, *zsrch_dir1, *zsrch_dir2;
GBLREF tp_frame *tp_pointer;
GBLREF int4 SPGC_since_LVGC; /* stringpool GCs since the last dead-data GC */
@@ -70,6 +68,9 @@ STATICFNDCL void als_xnew_killaliasarray(lvTree *lvt);
STATICFNDCL void als_prcs_xnew_alias_cntnr(lvTree *lvt, symval *popdsymval, symval *cursymval);
STATICFNDCL void als_prcs_markreached_cntnr(lvTree *lvt);
+DBGRFCT_ONLY(STATICDEF int resolve_alias_depth;)
+DBGRFCT_ONLY(STATICDEF int prcs_xnew_alias_depth;)
+DBGRFCT_ONLY(STATICDEF int prcs_xnew_reflist_depth;)
CONDITION_HANDLER(als_check_xnew_var_aliases_ch);
/* Define macros locally used by this routine only. General use macros are defined in alias.h */
@@ -161,16 +162,29 @@ CONDITION_HANDLER(als_check_xnew_var_aliases_ch);
} \
}
-/* Macro to clone an lv_val */
-#define CLONE_LVVAL(oldlv, newlv, cursymval) \
-{ \
- assert(LV_IS_BASE_VAR(oldlv)); \
- newlv = lv_getslot(cursymval); \
- *newlv = *oldlv; \
- LV_SYMVAL(newlv) = cursymval; \
- lv_var_clone(newlv, newlv); \
- oldlv->v.mvtype = MV_LVCOPIED; \
- oldlv->ptrs.copy_loc.newtablv = newlv; \
+/* Macro to clone an lv_val. Note clones to self because newlv is an exact copy of oldlv and we
+ * don't want to touch oldlv AT ALL during the cloning process. This effectively replaces the child
+ * tree.
+ */
+#define CLONE_LVVAL(oldlv, newlv, cursymval, popdsymval) \
+{ \
+ assert(LV_IS_BASE_VAR(oldlv)); \
+ newlv = lv_getslot(cursymval); \
+ DBGRFCT((stderr, "CLONE_LVVAL: Copy started - oldlv: 0x"lvaddr" newlv: 0x"lvaddr" cursymval: 0x"lvaddr" at " \
+ "%s at line %d\n", (oldlv), (newlv), (cursymval), __FILE__, __LINE__)); \
+ *newlv = *oldlv; \
+ assert(NULL == newlv->tp_var); \
+ LV_SYMVAL(newlv) = cursymval; \
+ lv_var_clone(newlv, newlv, FALSE); /* no refcnt maint here */ \
+ oldlv->v.mvtype = MV_LVCOPIED; \
+ oldlv->ptrs.copy_loc.newtablv = newlv; \
+ /* If popdsymval had alias activity, it is possible the alias activity got inherited into cursymval. \
+ * Since we cannot easily determine this for sure, err on the side of caution. \
+ */ \
+ if (popdsymval->alias_activity) \
+ cursymval->alias_activity = TRUE; \
+ DBGRFCT((stderr, "CLONE_LVVAL: Copy complete - oldlv: 0x"lvaddr" newlv: 0x"lvaddr" - refcnts of copied node: " \
+ "%d/%d\n", (oldlv), (newlv), (newlv)->stats.trefcnt, (newlv)->stats.crefcnt)); \
}
/* Macro to initialize a ZWR_ZAV_BLK structure */
@@ -185,16 +199,22 @@ CONDITION_HANDLER(als_check_xnew_var_aliases_ch);
* container var. Like the _CNTNRS_IN_TREE macros, in dbg mode, we will scan the array for containers even if has_aliascont
* flag is FALSE.
*/
-#define RESOLV_ALIAS_CNTNRS_IN_TREE(LV_BASE, POPDSYMVAL, CURSYMVAL) \
-{ \
- lvTree *lvt; \
- \
- if ((NULL != (lvt = LV_GET_CHILD(LV_BASE))) && ((LV_BASE)->stats.lvtaskcycle != lvtaskcycle) \
- PRO_ONLY(&& (LV_BASE)->has_aliascont)) \
- { \
- (LV_BASE)->stats.lvtaskcycle = lvtaskcycle; \
- als_prcs_xnew_alias_cntnr(lvt, POPDSYMVAL, CURSYMVAL); \
- } \
+#define RESOLV_ALIAS_CNTNRS_IN_TREE(LV_BASE, POPDSYMVAL, CURSYMVAL) \
+{ \
+ lvTree *lvt; \
+ \
+ if ((NULL != (lvt = LV_GET_CHILD(LV_BASE))) && ((LV_BASE)->stats.lvtaskcycle != lvtaskcycle) \
+ PRO_ONLY(&& (LV_BASE)->has_aliascont)) \
+ { \
+ DBGRFCT((stderr, "\nRESOLV_ALIAS_CNTNRS_IN_TREE: Beginning scan of lvbase 0x"lvaddr" at depth %d\n", \
+ (LV_BASE), ++resolve_alias_depth)); \
+ (LV_BASE)->stats.lvtaskcycle = lvtaskcycle; \
+ als_prcs_xnew_alias_cntnr(lvt, POPDSYMVAL, CURSYMVAL); \
+ DBGRFCT((stderr, "\nRESOLV_ALIAS_CNTNRS_IN_TREE: Completed scan of lvbase 0x"lvaddr" at depth %d\n", \
+ (LV_BASE), resolve_alias_depth--)); \
+ } else \
+ DBGRFCT((stderr, "\nRESOLV_ALIAS_CNTNRS_IN_TREE: Scan bypassed for 0x"lvaddr" because %s\n", (LV_BASE), \
+ (NULL == lvt) ? "has no children" : "already been processed")); \
}
/* Routine to repair the l_symtab entries in the stack due to hash table expansion such that the
@@ -304,8 +324,6 @@ void als_lsymtab_repair(hash_table_mname *table, ht_ent_mname *table_base_orig,
default:
continue;
}
- if (NULL == *htep)
- continue;
if ((*htep < table_base_orig) || (*htep >= table_top_orig))
/* Entry doesn't point to the current symbol table so ignore it since it didn't change */
continue;
@@ -333,7 +351,7 @@ CONDITION_HANDLER(als_check_xnew_var_aliases_ch)
* 1) If a variable was passed through to the new symtab and then was aliased to a var that belonged to the new symbol table,
* the lv_val in the old symtab was released and a new one assigned in the new symbol table. We have to:
* a) copy that value back to the previous symtab and
- * b) we have to fix the reference count since the alias owned by the new symtab is going away.
+ * b) we have to fix the reference count since the alias owned by the symtab being popped is going away.
* 2) If a variable is passed through to the new symtab and within that variable an alias container is created that points
* to a var in the newer symtab we need to copy that var/array back to the older symtab so the value remains.
* 3) This gets more interesting to deal with when that var is also aliased by a passed through variable (combining issues 1 & 2).
@@ -347,6 +365,9 @@ CONDITION_HANDLER(als_check_xnew_var_aliases_ch)
* a) Run the hash table looking for aliased variables. If found, do the reference count maintenance but don't worry about
* deleting any data since it will all go away after we return and unw_mv_ent() releases the symbol table and lv_blk chains.
* b) While running the hash table, run any variable trees we find anchored.
+ * Note we can only use the DECR_BASE_REF_LIGHT method when the lv_val is owned by the same symbol table as is being released.
+ * Else we need to use the regular DECR_BASE_REF() macro so the lv_val can be requeued to the proper queue and not be left in
+ * place where it causes problems later.
* 4) Go through the list of forwarded vars again (xnew_var_list) in the popped symval and see if any of the lv_vals are owned
* by the symval being popped. If they are, then the lv_vals involved need to be copied to lv_vals owned by the (now)
* current symtab because the popped symtab's lv_vals will be released by unw_mv_ent() when we return. Note that this also
@@ -372,7 +393,6 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
lv_val *lv, *prevlv, *currlv, *popdlv;
lv_val *newlv, *oldlv;
boolean_t bypass_lvscan, bypass_lvrepl;
- DBGRFCT_ONLY(mident_fixed vname;)
ESTABLISH(als_check_xnew_var_aliases_ch);
suspend_lvgcol = TRUE;
@@ -394,12 +414,29 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
xnewvar->lvval = (lv_val *)tabent->value; /* Cache lookup results for 2nd pass in step 4 */
delete_hashtab_ent_mname(popdsymtab, tabent);
}
- /* Step 3: Run popped hash table undoing alias references. */
- DBGRFCT((stderr, "als_check_xnew_var_aliases: Step 3 - running popped symtab tree undoing local refcounts\n"));
+ /* Step 3: Run popped hash table undoing alias references. Note that is is possible to find a local var that
+ * was NOT passed through here. For example:
+ *
+ * SET *a(1)=b ; Set a container to b
+ * NEW (a) ; Pass thru 'a'
+ * SET *b=a(1) ; Recreates 'b' as it was before but is not a resident of this array
+ *
+ * For this case, ignore the lv (don't decrement it) because we'll be handling that situation later.
+ */
+ DBGRFCT((stderr, "als_check_xnew_var_aliases: Step 3 - running popped symtab tree undoing local refcounts for all local "
+ "vars that were not passed-thru XNEW\n"));
for (htep = popdsymtab->base, htep_top = popdsymtab->top; htep < htep_top; htep++)
{
if (HTENT_VALID_MNAME(htep, lv_val, lv))
- DECR_BASE_REF_LIGHT(lv);
+ {
+ if (popdsymval == LV_SYMVAL(lv))
+ {
+ DECR_BASE_REF_LIGHT(lv); /* Just clean up ref counts */
+ } else
+ {
+ DECR_BASE_REF_NOSYM(lv, FALSE); /* lv_val not owned by popping symval */
+ }
+ }
}
/* Step 4: See what, if anything, needs to be copied from popped level to current level. There are 3 possible
* cases here. Note in all cases, we must decrement the use counters of prevlv since they were incremented in
@@ -408,7 +445,7 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
*
* Vars used:
*
- * prevlv == lv from the current symbol table.
+ * prevlv == lv from the current (popping-to) symbol table.
* currlv == lv we are going to eventually put into the current symbol table
* popdlv == lv from the popped symbol table
*
@@ -421,28 +458,24 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
* c) prevlv != popdlv && popdlv not in popd symtab. Same as case (a). Note this includes the case where popdlv
* already resides in cursymtab.
*/
- DBGRFCT((stderr, "als_check_xnew_var_aliases: Step 4 - beginning unwind scan of passed through vars\n"));
+ DBGRFCT((stderr, "\nals_check_xnew_var_aliases: Step 4 - beginning unwind scan of passed through vars\n"));
INCR_LVTASKCYCLE;
for (xnewvar = popdsymval->xnew_var_list; xnewvar; xnewvar = xnewvar_next)
{
bypass_lvscan = bypass_lvrepl = FALSE;
tabent = lookup_hashtab_mname(cursymtab, &xnewvar->key);
assert(tabent); /* Had better be there since it was passed in thru the exclusive new */
- DBGRFCT_ONLY(
- memcpy(vname.c, tabent->key.var_name.addr, tabent->key.var_name.len);
- vname.c[tabent->key.var_name.len] = '\0';
- );
prevlv = (lv_val *)tabent->value;
popdlv = xnewvar->lvval; /* Value of this var in popped symtab */
- DBGRFCT((stderr, "als_check_xnew_var_aliases: var '%s' prevlv: 0x"lvaddr" popdlv: 0x"lvaddr"\n",
- &vname.c, prevlv, popdlv));
+ DBGRFCT((stderr, "\nals_check_xnew_var_aliases: var '%.*s' prevlv: 0x"lvaddr" popdlv: 0x"lvaddr"\n",
+ tabent->key.var_name.len, tabent->key.var_name.addr, prevlv, popdlv));
if (prevlv == popdlv)
{ /* Case (a) - Just do the scan below */
currlv = prevlv;
bypass_lvrepl = TRUE;
} else if (popdsymval == LV_GET_SYMVAL(popdlv))
{ /* Case (b) - Clone the var and tree into blocks owned by current symtab with the caveat that we need not
- * do this if the array has already been cloned (because more than one var that was passed through it
+ * do this if the array has already been cloned (because more than one var that was passed through is
* pointing to it.
*/
if (MV_LVCOPIED == popdlv->v.mvtype)
@@ -458,7 +491,7 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
{
assert(LV_IS_BASE_VAR(popdlv));
/* lv_val is owned by the popped symtab .. clone it to the new current tree */
- CLONE_LVVAL(popdlv, currlv, cursymval);
+ CLONE_LVVAL(popdlv, currlv, cursymval, popdsymval);
DBGRFCT((stderr, "als_check_xnew_var_aliases: lv has been cloned from 0x"lvaddr" to 0x"lvaddr"\n",
popdlv, currlv));
}
@@ -474,14 +507,14 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
}
if (1 < prevlv->stats.trefcnt)
/* If prevlv is going to be around after we drop op_xnew's refcnt bumps, make sure it gets processed.
- * If it was processed above, then it is marked such and the macro will bypass processing it again.
+ * If it was processed above, then it is marked as such and the macro will bypass processing it again.
*/
RESOLV_ALIAS_CNTNRS_IN_TREE(prevlv, popdsymval, cursymval);
DECR_CREFCNT(prevlv); /* undo bump by op_xnew */
if (!bypass_lvrepl)
{ /* Replace the lvval in the current symbol table */
- DBGRFCT((stderr, "als_check_xnew_var_aliases: Resetting variable '%s' hte at 0x"lvaddr" from 0x"lvaddr
- " to 0x"lvaddr"\n", &vname.c, tabent, prevlv, currlv));
+ DBGRFCT((stderr, "als_check_xnew_var_aliases: Resetting variable '%.*s' hte at 0x"lvaddr" from 0x"lvaddr
+ " to 0x"lvaddr"\n", tabent->key.var_name.len, tabent->key.var_name.addr, tabent, prevlv, currlv));
tabent->value = (void *)currlv;
}
assert(1 <= prevlv->stats.trefcnt); /* verify op_xnew's bump is still there (may be only one) */
@@ -491,11 +524,11 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
xnewvar_anchor = xnewvar;
}
/* Step 5: See if anything on the xnew_ref_list needs to be handled */
- DBGRFCT((stderr, "als_check_xnew_var_aliases: Step 5: Process xnew_ref_list if any\n"));
+ DBGRFCT((stderr, "\n\nals_check_xnew_var_aliases: Step 5: Process xnew_ref_list if any\n"));
for (xnewref = popdsymval->xnew_ref_list; xnewref; xnewref = xnewref_next)
{
prevlv = xnewref->lvval;
- DBGRFCT((stderr, "als_check_xnew_var_aliases: xnewref-prevlv: 0x"lvaddr"\n", prevlv));
+ DBGRFCT((stderr, "\nals_check_xnew_var_aliases: xnewref-prevlv: 0x"lvaddr"\n", prevlv));
DECR_CREFCNT(prevlv); /* Will remove the trefcnt in final desposition below */
/* Only do the scan if the reference count is greater than 1 since we are going to remove the
* refcnts added by op_xnew as we finish here. So if the var is going away anyway, no need
@@ -503,10 +536,11 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
*/
if (1 < prevlv->stats.trefcnt)
{ /* Process the array */
- DBGRFCT((stderr, "als_check_xnew_var_aliases: potentially scanning lv 0x"lvaddr"\n", prevlv));
+ DBGRFCT((stderr, "als_check_xnew_var_aliases: potentially scanning lv 0x"lvaddr" due to refcnt > 1\n",
+ prevlv));
RESOLV_ALIAS_CNTNRS_IN_TREE(prevlv, popdsymval, cursymval);
} else
- DBGRFCT((stderr, "als_check_xnew_var_aliases: prevlv was deleted\n"));
+ DBGRFCT((stderr, "als_check_xnew_var_aliases: prevlv about to be deleted - scan bypassed\n"));
/* Remove refcnt and we are done */
DECR_BASE_REF_NOSYM(prevlv, TRUE);
xnewref_next = xnewref->next;
@@ -534,7 +568,7 @@ void als_check_xnew_var_aliases(symval *popdsymval, symval *cursymval)
assert(LV_IS_BASE_VAR(oldlv));
if (popdsymval == LV_SYMVAL(oldlv))
{ /* lv_val is owned by the popped symtab .. clone it to the new current tree */
- CLONE_LVVAL(oldlv, newlv, cursymval);
+ CLONE_LVVAL(oldlv, newlv, cursymval, popdsymval);
alias_retarg->str.addr = (char *)newlv; /* Replace container ptr */
DBGRFCT((stderr, "\nals_check_xnew_var_aliases: alias retarg var found - aliascont mval 0x"lvaddr
" being reset to point to lv 0x"lvaddr" which is a clone of lv 0x"lvaddr"\n",
@@ -599,7 +633,7 @@ STATICFNDEF void als_xnew_killaliasarray(lvTree *lvt)
/* Local routine!
* Routine to process an alias container found in a node of a var being "returned" back through an exclusive new.
- * We may have to move the data.
+ * We may have to move/copy the data.
*/
STATICFNDEF void als_prcs_xnew_alias_cntnr(lvTree *lvt, symval *popdsymval, symval *cursymval)
{
@@ -607,6 +641,8 @@ STATICFNDEF void als_prcs_xnew_alias_cntnr(lvTree *lvt, symval *popdsymval, symv
lvTreeNode *node;
lv_val *newlv, *oldlv;
+ DBGRFCT((stderr, "\nals_prcs_xnew_alias_cntnr: Entered to process tree 0x"lvaddr" with popping symval 0x"lvaddr
+ " and current (pop-to) symval 0x"lvaddr" level %d\n", lvt, popdsymval, cursymval, ++prcs_xnew_alias_depth));
assert(NULL != lvt); /* caller should not call if no subtree */
/* In the case of lv_killarray, the only option we have is to do post-order traversal since we are freeing
* nodes in the tree as we traverse. But in this case, we dont change the tree structure so we are free to
@@ -627,24 +663,24 @@ STATICFNDEF void als_prcs_xnew_alias_cntnr(lvTree *lvt, symval *popdsymval, symv
assert(LV_IS_BASE_VAR(newlv));
node->v.str.addr = (char *)newlv; /* Replace container ptr */
DBGRFCT((stderr, "\nals_prcs_xnew_alias_cntnr: aliascont var found - referenced array already "
- "copied - Setting pointer in aliascont lv 0x"lvaddr" to lv 0x"lvaddr"\n", node, newlv));
+ "copied - Setting pointer in aliascont node 0x"lvaddr" to lv 0x"lvaddr"\n", node, newlv));
} else
{
assert(LV_IS_BASE_VAR(oldlv));
if (popdsymval == LV_SYMVAL(oldlv))
{ /* lv_val is owned by the popped symtab .. clone it to the new current tree */
- CLONE_LVVAL(oldlv, newlv, cursymval);
+ CLONE_LVVAL(oldlv, newlv, cursymval, popdsymval);
assert(LV_IS_BASE_VAR(newlv));
node->v.str.addr = (char *)newlv; /* Replace container ptr */
- DBGRFCT((stderr, "\nals_prcs_xnew_alias_cntnr: aliascont var found - aliascont lv 0x"lvaddr
- " being reset to point to lv 0x"lvaddr" which is a clone of lv 0x"lvaddr"\n", node,
- newlv, oldlv));
+ DBGRFCT((stderr, "\nals_prcs_xnew_alias_cntnr: aliascont var found at node 0x"lvaddr
+ " being reset to point to lv 0x"lvaddr" which is a new copy of lv 0x"lvaddr
+ " which lived in previous symval -- scanning copied tree\n", node, newlv, oldlv));
} else
{ /* lv_val is owned by current or older symval .. just use it in the subsequent scan in case
* it leads us to other lv_vals owned by the popped symtab.
*/
- DBGRFCT((stderr, "\nals_prcs_xnew_alias_cntnr: aliascont var found - aliascont lv 0x"lvaddr
- " just being (potentially) scanned for container vars\n", node));
+ DBGRFCT((stderr, "\nals_prcs_xnew_alias_cntnr: aliascont var found at node 0x"lvaddr
+ " being (potentially) scanned for container vars\n", node));
newlv = oldlv;
}
RESOLV_ALIAS_CNTNRS_IN_TREE(newlv, popdsymval, cursymval);
@@ -654,6 +690,8 @@ STATICFNDEF void als_prcs_xnew_alias_cntnr(lvTree *lvt, symval *popdsymval, symv
if (NULL != lvt_child) /* Descend recursively down this tree as well */
als_prcs_xnew_alias_cntnr(lvt_child, popdsymval, cursymval);
}
+ DBGRFCT((stderr, "\nals_prcs_xnew_alias_cntnr: Processing complete for tree 0x"lvaddr" level %d\n\n", lvt,
+ prcs_xnew_alias_depth--));
}
/* Routine to process an alias container found in an array being "saved" by TSTART (op_tstart). We need to set this array up
@@ -678,7 +716,7 @@ void als_prcs_tpsav_cntnr(lvTree *lvt)
{
assert(lvt->base_lv->has_aliascont);
assert(!LV_IS_BASE_VAR(node));
- cntnr_lv_base = (lv_val *)node->v.str.addr; /* Extract container pointer */
+ cntnr_lv_base = (lv_val *)node->v.str.addr; /* Extract container pointer */
assert(NULL != cntnr_lv_base);
assert(LV_IS_BASE_VAR(cntnr_lv_base));
assert(1 <= cntnr_lv_base->stats.trefcnt);
@@ -686,34 +724,18 @@ void als_prcs_tpsav_cntnr(lvTree *lvt)
if (NULL == cntnr_lv_base->tp_var)
{ /* Save this var if it hasn't already been saved */
assert(cntnr_lv_base->stats.tstartcycle != tstartcycle);
- DBGRFCT((stderr, "\ntpSAV_container: Container at 0x"lvaddr
- " refers to lv 0x"lvaddr" -- Creating tpsav block\n", node, cntnr_lv_base));
- TP_SAVE_RESTART_VAR(cntnr_lv_base, tp_pointer, &null_mname_entry);
- INCR_CREFCNT(cntnr_lv_base); /* 2nd increment for reference via a container node */
- INCR_TREFCNT(cntnr_lv_base);
+ DBGRFCT((stderr, "\ntpSAV_container: Container at 0x"lvaddr" refers to lv 0x"lvaddr
+ " -- Creating tpsav block\n", node, cntnr_lv_base));
+ TP_SAVE_RESTART_VAR(cntnr_lv_base, tp_pointer, &null_mname_entry); /* increments refcnts */
if (LV_HAS_CHILD(cntnr_lv_base))
TPSAV_CNTNRS_IN_TREE(cntnr_lv_base);
} else
- { /* If not saving it, we still need to bump the ref count(s) for this reference and
- * process any children if we have't already seen this node (taskcycle check will tell us this).
+ { /* If already saved, we still need to bump the ref count(s) for this reference and
+ * process any children if we have't already seen this node (taskcycle check tells us this).
*/
DBGRFCT((stderr, "\ntpSAV_container: Container at 0x"lvaddr" refers to lv 0x"lvaddr
- " -- Incrementing refcnts\n", node, cntnr_lv_base));
- INCR_CREFCNT(cntnr_lv_base);
- INCR_TREFCNT(cntnr_lv_base);
- assert(0 < cntnr_lv_base->stats.trefcnt);
- assert(0 < cntnr_lv_base->stats.crefcnt);
- if (cntnr_lv_base->stats.tstartcycle != tstartcycle)
- {
- DBGRFCT((stderr, "\ntpSAV_container: .. Container at 0x"lvaddr" refers to lv 0x"lvaddr
- " -- processing tree\n", node, cntnr_lv_base));
- if (LV_HAS_CHILD(cntnr_lv_base))
- TPSAV_CNTNRS_IN_TREE(cntnr_lv_base);
- } else
- {
- DBGRFCT((stderr, "\ntpSAV_container: .. Container at 0x"lvaddr" refers to lv 0x"lvaddr
- " -- Already processed -- bypassing\n", node, cntnr_lv_base));
- }
+ " which already has a backup (tp_var 0x"lvaddr" -- bypassing\n", node, cntnr_lv_base,
+ cntnr_lv_base->tp_var));
}
}
lvt_child = LV_GET_CHILD(node);
@@ -722,84 +744,8 @@ void als_prcs_tpsav_cntnr(lvTree *lvt)
}
}
-/* For a given container var found in the tree we need to re-establish the reference counts for the base var
- * the container is pointing to. Used during a local var restore on a TP restart.
- */
-void als_prcs_tprest_cntnr(lvTree *lvt)
-{
- lvTree *lvt_child;
- lvTreeNode *node;
- lv_val *cntnr_lv_base;
-
- assert(NULL != lvt); /* caller should not call if no subtree */
- /* In the case of lv_killarray, the only option we have is to do post-order traversal since we are freeing
- * nodes in the tree as we traverse. But in this case, we dont change the tree structure so we are free to
- * choose any order. We choose in-order as that is faster than post-order.
- */
- for (node = lvAvlTreeFirst(lvt); NULL != node; node = lvAvlTreeNext(node))
- {
- if (node->v.mvtype & MV_ALIASCONT)
- {
- assert(lvt->base_lv->has_aliascont);
- assert(!LV_IS_BASE_VAR(node));
- cntnr_lv_base = (lv_val *)node->v.str.addr; /* Extract container pointer */
- assert(NULL != cntnr_lv_base);
- assert(LV_IS_BASE_VAR(cntnr_lv_base));
- assert(1 <= cntnr_lv_base->stats.trefcnt);
- assert(1 <= cntnr_lv_base->stats.crefcnt);
- assert(cntnr_lv_base->tp_var);
- DBGRFCT((stderr, "\ntpREST_cntnr_node: Processing container at 0x"lvaddr"\n", node));
- INCR_CREFCNT(cntnr_lv_base);
- INCR_TREFCNT(cntnr_lv_base);
- assert(0 < (cntnr_lv_base)->stats.trefcnt);
- assert(0 < (cntnr_lv_base)->stats.crefcnt);
- }
- lvt_child = LV_GET_CHILD(node);
- if (NULL != lvt_child) /* Descend recursively down this tree as well */
- als_prcs_tprest_cntnr(lvt_child);
- }
-}
-
-/* For a given container, decrement the ref count of the creature it points to. Part of unwinding an unmodified
- * tp saved variable.
- */
-void als_prcs_tpunwnd_cntnr(lvTree *lvt)
-{
- lvTree *lvt_child;
- lvTreeNode *node;
- lv_val *cntnr_lv_base;
-
- assert(NULL != lvt); /* caller should not call if no subtree */
- /* In the case of lv_killarray, the only option we have is to do post-order traversal since we are freeing
- * nodes in the tree as we traverse. But in this case, we dont change the tree structure so we are free to
- * choose any order. We choose in-order as that is faster than post-order.
- */
- for (node = lvAvlTreeFirst(lvt); NULL != node; node = lvAvlTreeNext(node))
- {
- if (node->v.mvtype & MV_ALIASCONT)
- {
- assert(lvt->base_lv->has_aliascont);
- assert(!LV_IS_BASE_VAR(node));
- cntnr_lv_base = (lv_val *)node->v.str.addr; /* Extract container pointer */
- assert(NULL != cntnr_lv_base);
- assert(LV_IS_BASE_VAR(cntnr_lv_base));
- assert(1 <= cntnr_lv_base->stats.trefcnt);
- assert(1 <= cntnr_lv_base->stats.crefcnt);
- /* Note we cannot assert cntnr_lv_base->tp_var here since the tp_var node may have already been freed and
- * cleared by unwind processing of the base var itself. We just have to undo our counts here and keep going.
- */
- DBGRFCT((stderr, "\ntpUNWND_cntnr_node: Processing container at 0x"lvaddr"\n", cntnr_lv_base));
- DECR_CREFCNT(cntnr_lv_base);
- DECR_BASE_REF_NOSYM(cntnr_lv_base, FALSE);
- }
- lvt_child = LV_GET_CHILD(node);
- if (NULL != lvt_child) /* Descend recursively down this tree as well */
- als_prcs_tpunwnd_cntnr(lvt_child);
- }
-}
-
-/* This routine deletes the data pointed to by the lv_val and removes the container flag from the value making it just
- * a regular NULL/0 value.
+/* This routine locates containers in the given array, removes the container type flag making the node a regular NULL/0 value and
+ * and decrements the reference counts of the lv_val the container pointed to thus removing the reference.
*/
void als_prcs_kill_cntnr(lvTree *lvt)
{
@@ -816,7 +762,7 @@ void als_prcs_kill_cntnr(lvTree *lvt)
{
if (node->v.mvtype & MV_ALIASCONT)
{
- assert(lvt->base_lv->has_aliascont);
+ assert(lvt->base_lv->has_aliascont); /* Verify flag is on if found container */
assert(!LV_IS_BASE_VAR(node));
cntnr_lv_base = (lv_val *)node->v.str.addr;
assert(NULL != cntnr_lv_base);
@@ -881,6 +827,8 @@ void als_prcs_xnewref_cntnr(lvTree *lvt)
* nodes in the tree as we traverse. But in this case, we dont change the tree structure so we are free to
* choose any order. We choose in-order as that is faster than post-order.
*/
+ DBGRFCT((stderr, "\nals_prcs_xnewref_cntnr: Starting to process lvTree 0x"lvaddr" at depth %d\n", lvt,
+ ++prcs_xnew_reflist_depth));
for (node = lvAvlTreeFirst(lvt); NULL != node; node = lvAvlTreeNext(node))
{
if (node->v.mvtype & MV_ALIASCONT)
@@ -892,8 +840,8 @@ void als_prcs_xnewref_cntnr(lvTree *lvt)
assert(LV_IS_BASE_VAR(cntnr_lv_base));
if (cntnr_lv_base->stats.lvtaskcycle != lvtaskcycle)
{
- INCR_CREFCNT(cntnr_lv_base);
INCR_TREFCNT(cntnr_lv_base);
+ INCR_CREFCNT(cntnr_lv_base);
cntnr_lv_base->stats.lvtaskcycle = lvtaskcycle;
if (NULL != xnewref_anchor)
{ /* Reuse entry from list */
@@ -910,6 +858,8 @@ void als_prcs_xnewref_cntnr(lvTree *lvt)
xnewref->lvval = cntnr_lv_base;
xnewref->next = curr_symval->xnew_ref_list;
curr_symval->xnew_ref_list = xnewref;
+ DBGRFCT((stderr, "als_prcs_xnewref_cntnr: Base lv at 0x"lvaddr" pointed to by container 0x"lvaddr
+ " added to xnewref list for subsequent processing\n", cntnr_lv_base, node));
if (LV_HAS_CHILD(cntnr_lv_base))
XNEWREF_CNTNRS_IN_TREE(cntnr_lv_base);
}
@@ -918,6 +868,8 @@ void als_prcs_xnewref_cntnr(lvTree *lvt)
if (NULL != lvt_child) /* Descend recursively down this tree as well */
als_prcs_xnewref_cntnr(lvt_child);
}
+ DBGRFCT((stderr, "\nals_prcs_xnewref_cntnr: Completed processing lvTree 0x"lvaddr" at depth %d\n", lvt,
+ prcs_xnew_reflist_depth--));
}
/* Initialize ZWRite hash table structures used when ZWRiting in an aliased variable environment */
@@ -1047,7 +999,7 @@ int als_lvval_gc(void)
lv_blk *lv_blk_ptr;
ht_ent_mname *htep, *htep_top;
lv_val *lvp, *lvlimit;
- lv_val **lvarraycur, **lvarray, **lvarraytop, **lvptr;
+ lv_val **lvarraycur = NULL, **lvarray = NULL, **lvarraytop, **lvptr;
mv_stent *mv_st_ent;
tp_frame *tf;
tp_var *restore_ent;
@@ -1059,11 +1011,6 @@ int als_lvval_gc(void)
SETUP_THREADGBL_ACCESS;
assert(!suspend_lvgcol);
DBGRFCT((stderr, "als_lvval_gc: Beginning lv_val garbage collection\n"));
- if (NULL == stp_array)
- /* Same initialization as is in stp_gcol_src.h */
- stp_array = (mstr **)malloc((stp_array_size = STP_MAXITEMS) * SIZEOF(mstr *));
- lvarraycur = lvarray = (lv_val **)stp_array;
- lvarraytop = lvarraycur + stp_array_size;
/* Steps 1,2 - find all the base lv_vals and put in list */
for (lv_blk_ptr = curr_symval->lv_first_block; lv_blk_ptr; lv_blk_ptr = lv_blk_ptr->next)
{
@@ -1073,16 +1020,10 @@ int als_lvval_gc(void)
sym = LV_SYMVAL(lvp);
assert((NULL == sym) || SYM_IS_SYMVAL(sym));
if ((NULL != sym) UNIX_ONLY(&& (TREF(zsearch_var) != lvp))
- UNIX_ONLY(&& (TREF(zsearch_dir1) != lvp) && (TREF(zsearch_dir2) != lvp)))
+ UNIX_ONLY(&& (TREF(zsearch_dir1) != lvp) && (TREF(zsearch_dir2) != lvp)))
{ /* Put it in the list */
assert(0 < lvp->stats.trefcnt);
- if (lvarraycur >= lvarraytop)
- { /* Need more room -- expand */
- stp_expand_array();
- lvarraycur = lvarray = (lv_val **)stp_array;
- lvarraytop = lvarraycur + stp_array_size;
- }
- *lvarraycur++ = lvp;
+ ADD_TO_STPARRAY(lvp, lvarray, lvarraycur, lvarraytop, lv_val);
}
}
}
@@ -1142,6 +1083,16 @@ int als_lvval_gc(void)
MARK_REACHABLE(mv_st_ent->mv_st_cont.mvs_nval.mvs_val);
assert(NULL != lvp);
break;
+ case MVST_LVAL:
+ /* This is a lv_val pushed by push_lvval. At this point in time gtmci.c is the only one
+ * that does this for return values and parameters. These need to be marked reachable
+ * as well even though they are not reachable from the lv hashtable.
+ */
+ lvp = mv_st_ent->mv_st_cont.mvs_lvval;
+ DBGRFCT((stderr, "als_lvval_gc: NVAL at 0x"lvaddr" has save value 0x"lvaddr"\n",
+ mv_st_ent, lvp));
+ assert(NULL != lvp);
+ break;
case MVST_STAB:
/* The symbol table is changing to be other than the table we are using so we can
* stop the loop now. Exiting the switch with lvp NULL indicates that.
@@ -1199,7 +1150,7 @@ int als_lvval_gc(void)
++killcnt;
if (LV_SYMVAL(lvp))
{ /* Var is still intact, kill it. Note that in this situation, since there are no hash table
- * entries pointing to us, our container refs and total refs should be equal. We can't
+ * entries pointing to the var, its container refs and total refs should be equal. We can't
* use the "regular" DECR macros because those get us into trouble. For example if this
* var has a container pointing to another var who has a container pointing to us and it
* is only those pointers keeping both vars alive, decrementing our counter causes it to
@@ -1220,7 +1171,7 @@ int als_lvval_gc(void)
}
DECR_BASE_REF_NOSYM(lvp, FALSE); /* Var might go away now, or later if need more deletes first */
} else
- DBGRFCT((stderr, "\nals_lvval_gc: Seems to have become released -- lvval 0x"lvaddr"\n", lvp));
+ DBGRFCT((stderr, "\nals_lvval_gc: Orphaned lvval 0x"lvaddr" has been freed\n", lvp));
}
}
DBGRFCT((stderr, "\nals_lvval_gc: final orphaned lvval scan completed\n"));
diff --git a/sr_port/anticipatory_freeze.h b/sr_port/anticipatory_freeze.h
index 13a66fd..97e545d 100644
--- a/sr_port/anticipatory_freeze.h
+++ b/sr_port/anticipatory_freeze.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012, 2013 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -53,7 +53,7 @@ error_def(ERR_TEXT);
#define ENABLE_FREEZE_ON_ERROR \
{ \
- if (ANTICIPATORY_FREEZE_AVAILABLE) \
+ if (INST_FREEZE_ON_ERROR_POLICY) \
{ /* Set anticipatory freeze function pointers to be used later (in send_msg and rts_error) */ \
is_anticipatory_freeze_needed_fnptr = &is_anticipatory_freeze_needed; \
set_anticipatory_freeze_fnptr = &set_anticipatory_freeze; \
@@ -63,10 +63,8 @@ error_def(ERR_TEXT);
#define CHECK_IF_FREEZE_ON_ERROR_NEEDED(CSA, MSG_ID, FREEZE_NEEDED, FREEZE_MSG_ID) \
{ \
GBLREF jnlpool_addrs jnlpool; \
- DCL_THREADGBL_ACCESS; \
\
- SETUP_THREADGBL_ACCESS; \
- if (!FREEZE_NEEDED && ANTICIPATORY_FREEZE_AVAILABLE && (NULL != is_anticipatory_freeze_needed_fnptr)) \
+ if (!FREEZE_NEEDED && CUSTOM_ERRORS_LOADED && (NULL != is_anticipatory_freeze_needed_fnptr)) \
{ /* NOT gtmsecshr */ \
if (IS_REPL_INST_UNFROZEN && (*is_anticipatory_freeze_needed_fnptr)((sgmnt_addrs *)CSA, MSG_ID)) \
{ \
@@ -111,18 +109,22 @@ error_def(ERR_TEXT);
}
#define AFREEZE_MASK 0x01
-#define ANTICIPATORY_FREEZE_AVAILABLE (0 != (TREF(gtm_custom_errors)).len)
+#define CUSTOM_ERRORS_AVAILABLE (0 != (TREF(gtm_custom_errors)).len)
+#define CUSTOM_ERRORS_LOADED ((NULL != jnlpool.jnlpool_ctl) \
+ && jnlpool.jnlpool_ctl->instfreeze_environ_inited)
+#define INST_FREEZE_ON_ERROR_POLICY (CUSTOM_ERRORS_AVAILABLE || CUSTOM_ERRORS_LOADED)
#define INSTANCE_FREEZE_HONORED(CSA) (DBG_ASSERT(NULL != CSA) \
((NULL != jnlpool.jnlpool_ctl) \
&& ((REPL_ALLOWED(((sgmnt_addrs *)CSA)->hdr)) \
|| mupip_jnl_recover /* recover or rollback */ \
|| ((sgmnt_addrs *)CSA)->nl->onln_rlbk_pid )))
-#define INST_FREEZE_ON_ERROR_ENABLED(CSA) (INSTANCE_FREEZE_HONORED(CSA) \
- && ANTICIPATORY_FREEZE_AVAILABLE \
+#define INST_FREEZE_ON_ERROR_ENABLED(CSA) (INSTANCE_FREEZE_HONORED(CSA) \
+ && CUSTOM_ERRORS_LOADED \
&& (((sgmnt_addrs *)CSA)->hdr->freeze_on_fail))
-#define INST_FREEZE_ON_NOSPC_ENABLED(CSA) (INST_FREEZE_ON_ERROR_ENABLED(CSA) \
+#define INST_FREEZE_ON_MSG_ENABLED(CSA, MSG) (INST_FREEZE_ON_ERROR_ENABLED(CSA) \
&& (NULL != is_anticipatory_freeze_needed_fnptr) \
- && (*is_anticipatory_freeze_needed_fnptr)(CSA, ERR_DSKNOSPCAVAIL))
+ && (*is_anticipatory_freeze_needed_fnptr)(CSA, MSG))
+#define INST_FREEZE_ON_NOSPC_ENABLED(CSA) INST_FREEZE_ON_MSG_ENABLED(CSA, ERR_DSKNOSPCAVAIL)
#define IS_REPL_INST_FROZEN ((NULL != jnlpool.jnlpool_ctl) && jnlpool.jnlpool_ctl->freeze)
#define IS_REPL_INST_UNFROZEN ((NULL != jnlpool.jnlpool_ctl) && !jnlpool.jnlpool_ctl->freeze)
@@ -336,7 +338,7 @@ void clear_fake_enospc_if_master_dead(void);
return_on_error))
#else /* #ifdef UNIX */
-# define ANTICIPATORY_FREEZE_AVAILABLE FALSE
+# define INST_FREEZE_ON_ERROR_POLICY FALSE
# define INST_FREEZE_ON_ERROR_ENABLED(CSA) FALSE
# define REPL_INST_AVAILABLE FALSE
# define WAIT_FOR_REPL_INST_UNFREEZE
diff --git a/sr_port/bx_boolop.c b/sr_port/bx_boolop.c
index a1455b3..d2bce8e 100644
--- a/sr_port/bx_boolop.c
+++ b/sr_port/bx_boolop.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -56,12 +56,21 @@ GBLREF command_qualifier cmd_qlf;
} \
}
+#define TRACK_JMP_TARGET(T, REF0) \
+{ /* T is triple to tag; REF0 is the new target with which it's tagged */ \
+ tripbp = &T->jmplist; /* borrow jmplist to track jmp targets */ \
+ assert(NULL == tripbp->bpt); \
+ assert((tripbp == tripbp->que.fl) && (tripbp == tripbp->que.bl)); \
+ tripbp->bpt = REF0; /* point to the new location */ \
+ dqins(TREF(bool_targ_ptr), que, tripbp); /* queue jmplist for clean-up */ \
+}
+
void bx_boolop(triple *t, boolean_t jmp_type_one, boolean_t jmp_to_next, boolean_t sense, oprtype *addr)
{
boolean_t expr_fini;
oprtype *adj_addr, *i, *p;
tbp *tripbp;
- triple *ref0, *ref1, *ref2, *t0, *t1;
+ triple *ref0, *ref1, *ref2, *t0, *t1, *tb, *tj;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -112,52 +121,52 @@ void bx_boolop(triple *t, boolean_t jmp_type_one, boolean_t jmp_to_next, boolean
for (i = t->operand; i < ARRAYTOP(t->operand); i++)
{
assert(NULL != TREF(boolchain_ptr));
- t1 = i->oprval.tref;
+ tb = i->oprval.tref;
if (&(t->operand[0]) == i)
- bx_tail(t1, jmp_type_one, p); /* do normal transform */
+ bx_tail(tb, jmp_type_one, p); /* do normal transform */
else
{ /* operand[1] */
- bx_tail(t1, sense, addr); /* do normal transform */
+ bx_tail(tb, sense, addr); /* do normal transform */
if (!expr_fini)
break; /* only need to relocate last operand[1] */
}
- if (OC_NOOP == t1->opcode)
+ if (OC_NOOP == tb->opcode)
{ /* the technique of sprinkling noops means fishing around for the actual instruction */
do
{
- t1 = t1->exorder.bl;
- assert(TREF(curtchain) != t1->exorder.bl);
- } while (OC_NOOP == t1->opcode);
- if ((oc_tab[t1->opcode].octype & OCT_JUMP) && (OC_JMPTSET != t1->opcode) && (OC_JMPTCLR != t1->opcode))
- t1 = t1->exorder.bl;
- if (OC_NOOP == t1->opcode)
+ tb = tb->exorder.bl;
+ assert(TREF(curtchain) != tb->exorder.bl);
+ } while (OC_NOOP == tb->opcode);
+ if ((oc_tab[tb->opcode].octype & OCT_JUMP) && (OC_JMPTSET != tb->opcode) && (OC_JMPTCLR != tb->opcode))
+ tb = tb->exorder.bl;
+ if (OC_NOOP == tb->opcode)
{
- for (t1 = i->oprval.tref; OC_NOOP == t1->opcode; t1 = t1->exorder.fl)
- assert(TREF(curtchain) != t1->exorder.fl);
+ for (tb = i->oprval.tref; OC_NOOP == tb->opcode; tb = tb->exorder.fl)
+ assert(TREF(curtchain) != tb->exorder.fl);
}
}
- assert(OC_NOOP != t1->opcode);
- assert((oc_tab[t1->exorder.fl->opcode].octype & OCT_JUMP)
- ||(OC_JMPTSET != t1->exorder.fl->opcode) || (OC_JMPTCLR != t1->exorder.fl->opcode));
- ref0 = maketriple(t1->opcode); /* copy operation for place in new ladder */
+ assert(OC_NOOP != tb->opcode);
+ assert((oc_tab[tb->exorder.fl->opcode].octype & OCT_JUMP)
+ || (OC_JMPTSET != tb->exorder.fl->opcode) || (OC_JMPTCLR != tb->exorder.fl->opcode));
+ ref0 = maketriple(tb->opcode); /* copy operation for place in new ladder */
ref1 = (TREF(boolchain_ptr))->exorder.bl; /* common setup for above op insert */
- switch (t1->opcode)
+ switch (tb->opcode)
{ /* time to subvert original jump ladder entry */
case OC_COBOOL:
/* insert COBOOL and copy of following JMP in boolchain; overlay them with STOTEMP and NOOP */
- assert(TRIP_REF == t1->operand[0].oprclass);
+ assert(TRIP_REF == tb->operand[0].oprclass);
dqins(ref1, exorder, ref0);
- if (oc_tab[t1->operand[0].oprval.tref->opcode].octype & OCT_MVAL)
+ if (oc_tab[tb->operand[0].oprval.tref->opcode].octype & OCT_MVAL)
{ /* do we need a STOTEMP? */
- STOTEMP_IF_NEEDED(ref0, 0, t1, t1->operand[0]);
+ STOTEMP_IF_NEEDED(ref0, 0, tb, tb->operand[0]);
} else
{ /* make it an mval instead of COBOOL now */
- t1->opcode = OC_COMVAL;
- ref0->operand[0] = put_tref(t1); /* new COBOOL points to this OC_COMVAL */
+ tb->opcode = OC_COMVAL;
+ ref0->operand[0] = put_tref(tb); /* new COBOOL points to this OC_COMVAL */
}
- t1 = t1->exorder.fl;
- ref0 = maketriple(t1->opcode); /* create new jmp on result of coerce */
- ref0->operand[0] = t1->operand[0];
+ t1 = tb->exorder.fl;
+ tj = maketriple(t1->opcode); /* create new jmp on result of coerce */
+ tj->operand[0] = t1->operand[0];
t1->opcode = OC_NOOP; /* wipe out original jmp */
t1->operand[0].oprclass = NO_REF;
break;
@@ -168,24 +177,23 @@ void bx_boolop(triple *t, boolean_t jmp_type_one, boolean_t jmp_to_next, boolean
case OC_PATTERN:
case OC_SORTS_AFTER:
/* insert copies of orig OC and following JMP in boolchain & overly originals with STOTEMPs */
- assert(TRIP_REF == t1->operand[0].oprclass);
- assert(TRIP_REF == t1->operand[1].oprclass);
+ assert(TRIP_REF == tb->operand[0].oprclass);
+ assert(TRIP_REF == tb->operand[1].oprclass);
dqins(ref1, exorder, ref0);
- STOTEMP_IF_NEEDED(ref0, 0, t1, t1->operand[0]);
- ref1 = t1;
- t1 = t1->exorder.fl;
- ref2 = maketriple(t1->opcode); /* copy jmp */
- ref2->operand[0] = t1->operand[0];
- STOTEMP_IF_NEEDED(ref0, 1, t1, ref1->operand[1]);
- if (OC_NOOP == ref1->opcode) /* does op[0] need cleanup? */
- ref1->operand[0].oprclass = ref1->operand[1].oprclass = NO_REF;
- ref0 = ref2;
+ STOTEMP_IF_NEEDED(ref0, 0, tb, tb->operand[0]);
+ t1 = tb->exorder.fl;
+ tj = maketriple(t1->opcode); /* copy jmp */
+ tj->operand[0] = t1->operand[0];
+ STOTEMP_IF_NEEDED(ref0, 1, t1, tb->operand[1]);
+ if (OC_NOOP == tb->opcode) /* does op[0] need cleanup? */
+ tb->operand[0].oprclass = tb->operand[1].oprclass = NO_REF;
break;
case OC_JMPTSET:
case OC_JMPTCLR:
- /* move copy of jmp to boolchain and NOOP it */
- ref0->operand[0] = t1->operand[0]; /* new jmpt gets old target */
- ref2 = maketriple(OC_NOOP); /* insert a NOOP in new chain inplace of COBOOL */
+ t1 = tb; /* move copy of jmp to boolchain and NOOP it */
+ tj = ref0;
+ tj->operand[0] = t1->operand[0]; /* new jmpt gets old target */
+ ref2 = maketriple(OC_NOOP); /* insert a NOOP in new chain in place of COBOOL */
dqins(ref1, exorder, ref2);
t1->opcode = OC_NOOP; /* wipe out original jmp */
t1->operand[0].oprclass = NO_REF;
@@ -195,18 +203,15 @@ void bx_boolop(triple *t, boolean_t jmp_type_one, boolean_t jmp_to_next, boolean
}
assert((OC_STOTEMP == t1->opcode) || (OC_NOOP == t1->opcode) || (OC_COMVAL == t1->opcode)
|| (OC_LITC == t1->opcode));
- assert(oc_tab[ref0->opcode].octype & OCT_JUMP);
+ assert(oc_tab[tj->opcode].octype & OCT_JUMP);
ref1 = (TREF(boolchain_ptr))->exorder.bl;
- dqins(ref1, exorder, ref0); /* common insert for new jmp */
+ dqins(ref1, exorder, tj); /* common insert for new jmp */
+ TRACK_JMP_TARGET(tb, ref0);
}
assert(oc_tab[t->opcode].octype & OCT_BOOL);
t->opcode = OC_NOOP; /* wipe out the original boolean op */
t->operand[0].oprclass = t->operand[1].oprclass = NO_REF;
- tripbp = &t->jmplist; /* borrow jmplist to track jmp targets */
- assert(NULL == tripbp->bpt);
- assert((tripbp == tripbp->que.fl) && (tripbp == tripbp->que.bl));
- tripbp->bpt = jmp_to_next ? (TREF(boolchain_ptr))->exorder.bl : ref0; /* point op triple at op[1] position or op[0] */
- dqins(TREF(bool_targ_ptr), que, tripbp); /* queue jmplist for clean-up */
+ TRACK_JMP_TARGET(t, jmp_to_next ? (TREF(boolchain_ptr))->exorder.bl : ref0); /* point at op[1] or op[0] respectively */
if (!expr_fini)
return;
/* time to deal with new jump ladder */
@@ -215,15 +220,15 @@ void bx_boolop(triple *t, boolean_t jmp_type_one, boolean_t jmp_to_next, boolean
assert(TREF(bool_targ_ptr) != (TREF(bool_targ_ptr))->que.fl);
assert(t0->exorder.bl == t);
assert(t0 == t->exorder.fl);
- dqadd(t, TREF(boolchain_ptr), exorder); /* insert the new jump ladder */
+ dqadd(t, TREF(boolchain_ptr), exorder); /* insert the new jump ladder */
ref0 = (TREF(boolchain_ptr))->exorder.bl->exorder.fl;
- t0 = t->exorder.fl;
if (ref0 == TREF(curtchain))
{ /* add a safe target */
newtriple(OC_NOOP);
ref0 = (TREF(curtchain))->exorder.bl;
}
- assert((OC_COBOOL == t0->opcode) ||(OC_JMPTSET != t0->opcode) || (OC_JMPTCLR != t0->opcode)) ;
+ t0 = t->exorder.fl;
+ assert((OC_COBOOL == t0->opcode) || (OC_JMPTSET != t0->opcode) || (OC_JMPTCLR != t0->opcode)) ;
t0 = t0->exorder.fl;
assert(oc_tab[t0->opcode].octype & OCT_JUMP);
for (; (t0 != ref0) && oc_tab[t0->opcode].octype & OCT_JUMP; t0 = t0->exorder.fl)
@@ -232,8 +237,20 @@ void bx_boolop(triple *t, boolean_t jmp_type_one, boolean_t jmp_to_next, boolean
assert(INDR_REF == adj_addr->oprclass);
if (NULL != (t1 = (adj_addr = adj_addr->oprval.indr)->oprval.tref))
{ /* need to adjust target; NOTE assignments above */
- if (OC_BOOLFINI != t1->opcode)
- { /* not past the end of the new chain */
+ if (TNXT_REF == adj_addr->oprclass) /* TNXT requires a different adjustment */
+ {
+ for (ref1 = t1->exorder.fl; ref1 != ref0; ref1 = ref1->exorder.fl)
+ {
+ if (NULL != ref1->jmplist.bpt) /* find 1st recorded target after TNXT */
+ {
+ assert((OC_NOOP == ref1->opcode) || (OC_STOTEMP == ref1->opcode));
+ ref1 = ref1->jmplist.bpt; /* should point to appropriate new target */
+ assert((oc_tab[ref1->opcode].octype & OCT_BOOL) || (OC_NOOP == ref1->opcode));
+ break;
+ }
+ }
+ } else
+ {
assert(TJMP_REF == adj_addr->oprclass);
if ((t == t1) || (t1 == ref0))
ref1 = ref0; /* adjust to end of boolean expression */
@@ -257,8 +274,8 @@ void bx_boolop(triple *t, boolean_t jmp_type_one, boolean_t jmp_to_next, boolean
|| (OC_JMPTSET == ref1->exorder.fl->opcode)
|| (TREF(curtchain) == ref1->exorder.fl))));
}
- t0->operand[0] = put_tjmp(ref1); /* no indrection simplifies later interations */
}
+ t0->operand[0] = put_tjmp(ref1); /* no indirection simplifies later interations */
}
t0 = t0->exorder.fl;
if ((OC_BOOLFINI == t0->opcode) || (TREF(curtchain) == t0->exorder.fl))
diff --git a/sr_port/cert_blk.c b/sr_port/cert_blk.c
index 46ecb49..a779c33 100644
--- a/sr_port/cert_blk.c
+++ b/sr_port/cert_blk.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -70,6 +70,7 @@ error_def(ERR_DBDIRTSUBSC);
error_def(ERR_DBMAXNRSUBS); /* same error as ERR_MAXNRSUBSCRIPTS, but has a string output as well */
error_def(ERR_DBINVGBL);
error_def(ERR_DBBDBALLOC);
+error_def(ERR_GVINVALID);
#define BITS_PER_UCHAR 8
#define BLKS_PER_UINT4 ((SIZEOF(uint4) / SIZEOF(unsigned char)) * BITS_PER_UCHAR) / BML_BITS_PER_BLK
@@ -86,7 +87,7 @@ error_def(ERR_DBBDBALLOC);
#define RTS_ERROR_FUNC(CSA, ERR, BUFF) \
{ \
if (gtmassert_on_error) \
- GTMASSERT; \
+ assertpro(0 != ERR); \
rts_error_csa(CSA_ARG(CSA) VARLSTCNT(4) MAKE_MSG_INFO(ERR), 2, LEN_AND_STR((char_ptr_t)BUFF)); \
}
@@ -304,7 +305,10 @@ int cert_blk (gd_region *reg, block_id blk, blk_hdr_ptr_t bp, block_id root, boo
{
ch = *((sm_uc_ptr_t)rp + SIZEOF(rec_hdr));
if (!(VALFIRSTCHAR_WITH_TRIG(ch)))
- GTMASSERT;
+ {
+ RTS_ERROR_FUNC(csa, ERR_GVINVALID, util_buff);
+ return FALSE;
+ }
}
}
if (r_top == (rec_hdr_ptr_t)blk_top && blk_levl)
diff --git a/sr_port/cmd.c b/sr_port/cmd.c
index 7f8a38d..823d70f 100644
--- a/sr_port/cmd.c
+++ b/sr_port/cmd.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -97,6 +97,9 @@ LITDEF nametabent cmd_names[] =
,{2, "ZL"}, {5, "ZLINK"}
,{2, "ZM"}, {8, "ZMESSAGE"}
,{2, "ZP"}, {6, "ZPRINT"}
+# ifdef USHBIN_SUPPORTED
+ ,{3, "ZRU"}, {8, "ZRUPDATE"}
+# endif
,{3, "ZSH"}, {5, "ZSHOW"}
,{3, "ZST"}, {5, "ZSTEP"}
,{3, "ZSY"}, {7, "ZSYSTEM"}
@@ -131,7 +134,7 @@ LITDEF unsigned char cmd_index[27] =
{
0, 0, 2, 4, 6, 8, 10, 12, 15, 17, 19, 21, 23
,25, 27, 29, 29, 31, 33, 35, 43, 45, 47, 49
- ,51, 51, GTMTRIG_ONLY(96) NON_GTMTRIG_ONLY(94)
+ ,51, 51, 94 GTMTRIG_ONLY(+ 2) USHBIN_ONLY(+ 2) /* add ztrigger and zrupdate, respectively */
};
LITDEF struct
{
@@ -186,6 +189,9 @@ LITDEF struct
,{m_zlink, 1, 1, ALL_SYS}, {m_zlink, 1, 1, ALL_SYS}
,{m_zmessage, 0, 1, ALL_SYS}, {m_zmessage, 0, 1, ALL_SYS}
,{m_zprint, 1, 1, ALL_SYS}, {m_zprint, 1, 1, ALL_SYS}
+# ifdef USHBIN_SUPPORTED
+ ,{m_zrupdate, 0, 1, ALL_SYS}, {m_zrupdate, 0, 1, ALL_SYS}
+# endif
,{m_zshow, 1, 1, ALL_SYS}, {m_zshow, 1, 1, ALL_SYS}
,{m_zstep, 1, 1, ALL_SYS}, {m_zstep, 1, 1, ALL_SYS}
,{m_zsystem, 1, 1, ALL_SYS}, {m_zsystem, 1, 1, ALL_SYS}
@@ -288,7 +294,7 @@ LITDEF struct
if (fetch0 != curr_fetch_trip)
{
assert(OC_FETCH == curr_fetch_trip->opcode);
- *cr = put_tjmp((TREF(curtchain))->exorder.bl);
+ *cr = put_tjmp(curr_fetch_trip);
} else
{
if (shifting)
diff --git a/sr_port/cmd.h b/sr_port/cmd.h
index 477fe93..519b243 100644
--- a/sr_port/cmd.h
+++ b/sr_port/cmd.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -55,6 +55,9 @@ int m_zinvcmd(void);
int m_zlink(void);
int m_zmessage(void);
int m_zprint(void);
+#ifdef USHBIN_SUPPORTED
+int m_zrupdate(void);
+#endif
int m_zshow(void);
int m_zstep(void);
int m_zsystem(void);
@@ -66,5 +69,4 @@ int m_ztstart(void);
int m_zwatch(void);
int m_zwithdraw(void);
int m_zwrite(void);
-
#endif
diff --git a/sr_port/cmd_qlf.h b/sr_port/cmd_qlf.h
index e0e93b1..cbe942e 100644
--- a/sr_port/cmd_qlf.h
+++ b/sr_port/cmd_qlf.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,7 +42,8 @@ typedef struct
#define CQ_ALIGN_STRINGS (1 << 11) /* 0x0800 */
#define CQ_UTF8 (1 << 12) /* 0x1000 */
#define CQ_NAMEOFRTN (1 << 13) /* 0x2000 */
-#define CQ_DYNAMIC_LITERALS (1 << 14) /* 0x4000 -- Set via environmental variable gtm_dynamic_literals (gtm_logicals.h) */
+#define CQ_DYNAMIC_LITERALS (1 << 14) /* 0x4000 */
+#define CQ_EMBED_SOURCE (1 << 15) /* 0x8000 */
/* TODO: add CQ_ALIGN_STRINGS to the default list below when alignment is supported */
#define CQ_DEFAULT (CQ_WARNINGS | CQ_OBJECT | CQ_IGNORE | CQ_LOWER_LABELS | CQ_LINE_ENTRY | CQ_INLINE_LITERALS)
@@ -66,8 +67,8 @@ typedef struct src_line_type
{
struct src_line_type *fl,*bl;
} que;
- char *addr;
- int4 line;
+ mstr str; /* M source string */
+ int4 line; /* line number */
} src_line_struct;
void zl_cmd_qlf(mstr *quals, command_qualifier *qualif);
diff --git a/sr_port/code_gen.c b/sr_port/code_gen.c
index a35d9a8..8df4b9f 100644
--- a/sr_port/code_gen.c
+++ b/sr_port/code_gen.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -10,6 +10,9 @@
****************************************************************/
#include "mdef.h"
+
+#include "gtm_string.h"
+
#include "compiler.h"
#include "opcode.h"
#include "mdq.h"
@@ -54,13 +57,17 @@ void code_gen(void)
if (ct->src.line != old_line)
{
list_line("");
- for (sl = src_head.que.bl; sl->line <= ct->src.line && sl != &src_head; )
+ dqloop(&src_head, que, sl)
{
+ if (sl->line > ct->src.line)
+ break;
+ assert(sl->str.len == STRLEN(sl->str.addr));
+ NEWLINE_TO_NULL(sl->str.addr[sl->str.len - 1]);
list_line_number();
- dqdel(sl,que);
- list_line(sl->addr);
- sl = src_head.que.bl;
+ list_line(sl->str.addr);
}
+ /* Delete traversed lines, so we don't list them again during subsequent iters of the outer loop */
+ dqdelchain(&src_head, sl, que);
old_line = ct->src.line;
}
}
diff --git a/sr_port/gtm_imagetype_init.c b/sr_port/common_startup_init.c
similarity index 61%
rename from sr_port/gtm_imagetype_init.c
rename to sr_port/common_startup_init.c
index cf140fd..0d0c0d8 100644
--- a/sr_port/gtm_imagetype_init.c
+++ b/sr_port/common_startup_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,8 +14,13 @@
#include "gtm_stdlib.h"
#include "gtm_string.h"
+#include "gt_timer.h"
+#include "gtm_env_init.h"
+#include "get_page_size.h"
+#include "getjobnum.h"
#include "gtmimagename.h"
-#include "gtm_imagetype_init.h"
+#include "gtm_utf8.h"
+#include "common_startup_init.h"
GBLREF boolean_t skip_dbtriggers;
GBLREF boolean_t is_replicator;
@@ -29,20 +34,47 @@ GBLREF boolean_t span_nodes_disallowed;
GBLREF char gtm_dist[GTM_PATH_MAX];
#endif
-void gtm_imagetype_init(enum gtmImageTypes img_type)
+void common_startup_init(enum gtmImageTypes img_type)
{
- boolean_t is_svc_or_gtcm;
+ boolean_t is_gtcm;
char *dist;
- int len = 0;
+ int len;
+ /* First set the global variable image_type. */
+ image_type = img_type;
+ /* Get the process ID. */
+ getjobnum();
+ /* Get the OS page size. */
+ get_page_size();
+# ifdef UNIX
+ /* Read gtm_dist. */
+ if (NULL != (dist = GETENV(GTM_DIST)))
+ {
+ len = STRLEN(dist);
+ len = (GTM_PATH_MAX < len) ? GTM_PATH_MAX : len;
+ memcpy(gtm_dist, dist, len);
+ gtm_dist[len] = '\0';
+ }
+ /* Setup global variables corresponding to signal blocks. */
+ set_blocksig();
+ /* Do common environment initialization. */
+ gtm_env_init();
+ /* GT.M typically opens journal pool during the first update (in gvcst_put, gvcst_kill or op_ztrigger). But, if
+ * anticipatory freeze is enabled, we want to open journal pool for any reads done by GT.M as well (basically at the time
+ * of first database open (in gvcst_init). So, set jnlpool_init_needed to TRUE if this is GTM_IMAGE.
+ */
+ jnlpool_init_needed = (GTM_IMAGE == img_type);
+ /* Set gtm_wcswidth_fnptr for util_output to work correctly in UTF-8 mode. This is needed only for utilities that can
+ * operate on UTF-8 mode.
+ */
+ gtm_wcswidth_fnptr = (GTMSECSHR_IMAGE == img_type) ? NULL : gtm_wcswidth;
+# endif
NON_GTMTRIG_ONLY(skip_dbtriggers = TRUE;) /* Do not invoke triggers for trigger non-supporting platforms. */
UNIX_ONLY(span_nodes_disallowed = (GTCM_GNP_SERVER_IMAGE == img_type) || (GTCM_SERVER_IMAGE == img_type);)
- is_svc_or_gtcm = ((GTM_SVC_DAL_IMAGE == img_type)
- || (GTCM_GNP_SERVER_IMAGE == img_type)
- || (GTCM_SERVER_IMAGE == img_type));
- if (is_svc_or_gtcm)
- skip_dbtriggers = TRUE; /* SUN RPC DAL server and GT.CM OMI and GNP servers do not invoke triggers */
- if (is_svc_or_gtcm || (GTM_IMAGE == img_type))
+ is_gtcm = ((GTCM_GNP_SERVER_IMAGE == img_type) || (GTCM_SERVER_IMAGE == img_type));
+ if (is_gtcm)
+ skip_dbtriggers = TRUE; /* GT.CM OMI and GNP servers do not invoke triggers */
+ if (is_gtcm || (GTM_IMAGE == img_type))
{
is_replicator = TRUE; /* can go through t_end() and write jnl records to the jnlpool for replicated db */
run_time = TRUE;
@@ -54,23 +86,7 @@ void gtm_imagetype_init(enum gtmImageTypes img_type)
# ifdef UNIX
else if (MUPIP_IMAGE == img_type)
run_time = FALSE;
- /* GT.M typically opens journal pool during the first update (in gvcst_put, gvcst_kill or op_ztrigger). But, if
- * anticipatory freeze is enabled, we want to open journal pool for any reads done by GT.M as well (basically at the time
- * of first database open (in gvcst_init). So, set jnlpool_init_needed to TRUE if this is GTM_IMAGE.
- */
- jnlpool_init_needed = (GTM_IMAGE == img_type);
- /* Read gtm_dist here and use this value everywhere else */
- dist = (char *)GETENV(GTM_DIST);
- if (dist)
- len = STRLEN(dist);
- if(len)
- {
- memcpy(gtm_dist, dist, ((len > GTM_PATH_MAX) ? GTM_PATH_MAX : len));
- gtm_dist[GTM_PATH_MAX - 1] = '\0';
- }
- else
- gtm_dist[0] = '\0';
# endif
- image_type = img_type;
return;
}
+
diff --git a/sr_unix/gtm_startup_chk.h b/sr_port/common_startup_init.h
similarity index 68%
copy from sr_unix/gtm_startup_chk.h
copy to sr_port/common_startup_init.h
index 5bd5e7c..389d24b 100644
--- a/sr_unix/gtm_startup_chk.h
+++ b/sr_port/common_startup_init.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,10 +9,9 @@
* *
****************************************************************/
-#ifndef __GTM_STARTUP_CHK_H__
-#define __GTM_STARTUP_CHK_H__
+#ifndef _COMMON_STARTUP_INIT_DEFINED
+#define _COMMON_STARTUP_INIT_DEFINED
-int gtm_chk_dist(char *image);
-int gtm_chk_image(void);
+void common_startup_init(enum gtmImageTypes img_type);
#endif
diff --git a/sr_port/compiler.h b/sr_port/compiler.h
index 5aed7a0..30b87ff 100644
--- a/sr_port/compiler.h
+++ b/sr_port/compiler.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -485,6 +485,16 @@ typedef struct
--(TREF(for_stack_ptr)); \
}
+/* The following macro should be used when doing an OC_FETCH other than at the start of a line because
+ * it deals with the possibility that there is a preceding FOR, in which case, we use start_for_fetches to
+ * be sure the new fetch includes any FOR loop control variable
+ */
+#define MID_LINE_REFETCH \
+ if (TREF(for_stack_ptr) == TADR(for_stack)) \
+ start_fetches(OC_FETCH); \
+ else /* if in the body of a FOR loop we need to ensure the control variable is refetched */ \
+ start_for_fetches();
+
/* $TEXT(+n^rtn) fetches from the most recently ZLINK'd version of rtn. $TEXT(+n) fetches from the currently executing version.
* The compiler converts $TEXT(+n) to $TEXT(+n^!), indicating at runtime $TEXT should fetch from the current executing routine.
* '!' is not a legal routine name character.
@@ -498,6 +508,12 @@ typedef struct
&& (0 == MEMCMP_LIT((S)->addr, CURRENT_RTN_STRING)))
#define WANT_CURRENT_RTN(R) WANT_CURRENT_RTN_MSTR(&(R)->str)
+#define NEWLINE_TO_NULL(C) \
+{ \
+ if ('\n' == (char)(C)) \
+ C = '\0'; \
+}
+
int actuallist(oprtype *opr);
int bool_expr(boolean_t op, oprtype *addr);
void bx_boolop(triple *t, boolean_t jmp_type_one, boolean_t jmp_to_next, boolean_t sense, oprtype *addr);
@@ -567,8 +583,10 @@ int f_zparse(oprtype *a, opctype op);
int f_zpeek(oprtype *a, opctype op);
int f_zprevious(oprtype *a, opctype op);
int f_zqgblmod(oprtype *a, opctype op);
+int f_zrupdate(oprtype *a, opctype op);
int f_zsearch(oprtype *a, opctype op);
int f_zsigproc(oprtype *a, opctype op);
+int f_zsocket(oprtype *a, opctype op);
int f_zsqlexpr (oprtype *a, opctype op);
int f_zsqlfield (oprtype *a, opctype op);
int f_zsubstr(oprtype *a, opctype op);
diff --git a/sr_port/compiler_startup.c b/sr_port/compiler_startup.c
index abe5147..732782e 100644
--- a/sr_port/compiler_startup.c
+++ b/sr_port/compiler_startup.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -54,16 +54,17 @@ boolean_t compiler_startup(void)
#ifdef DEBUG
void dumpall();
#endif
- boolean_t compile_w_err;
+ boolean_t compile_w_err, need_source_lines, use_src_queue, creating_list_file;
unsigned char err_buf[45];
unsigned char *cp, *cp2;
int errknt;
int4 n;
- uint4 line_count;
+ uint4 line_count, total_source_len;
mlabel *null_lab;
src_line_struct *sl;
mident null_mident;
gtm_rtn_src_chksum_ctx checksum_ctx;
+ mstr str;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -95,11 +96,15 @@ boolean_t compiler_startup(void)
}
rtn_src_chksum_init(&checksum_ctx);
cg_phase = CGP_PARSE;
- if (cmd_qlf.qlf & CQ_LIST || cmd_qlf.qlf & CQ_CROSS_REFERENCE)
+ creating_list_file = (cmd_qlf.qlf & CQ_LIST) || (cmd_qlf.qlf & CQ_CROSS_REFERENCE);
+ need_source_lines = (cmd_qlf.qlf & CQ_EMBED_SOURCE) || creating_list_file;
+ use_src_queue = (cmd_qlf.qlf & CQ_EMBED_SOURCE) || (creating_list_file && (cmd_qlf.qlf & CQ_MACHINE_CODE));
+ if (need_source_lines)
{
- if (cmd_qlf.qlf & CQ_MACHINE_CODE)
+ if (use_src_queue)
dqinit(&src_head, que);
- open_list_file();
+ if (creating_list_file)
+ open_list_file();
}
if (cmd_qlf.qlf & CQ_CE_PREPROCESS)
open_ceprep_file();
@@ -111,28 +116,32 @@ boolean_t compiler_startup(void)
curr_fetch_count = 0;
TREF(code_generated) = FALSE;
line_count = 1;
+ total_source_len = 0;
for (source_line = 1; errknt <= HOPELESS_COMPILE; source_line++)
{
if (-1 == (n = read_source_file()))
break;
rtn_src_chksum_line(&checksum_ctx, source_buffer, n);
- if ('\n' == source_buffer[n - 1])
- source_buffer[n - 1] = '\0'; /* compiler doesn't like trailing newlines (gives SPOREOL errors) */
- if (cmd_qlf.qlf & CQ_LIST || cmd_qlf.qlf & CQ_CROSS_REFERENCE)
+ if (need_source_lines)
{
- if (cmd_qlf.qlf & CQ_MACHINE_CODE)
- {
+ if (use_src_queue)
+ { /* Accumulate list of M source lines */
sl = (src_line_struct *)mcalloc(SIZEOF(src_line_struct));
- dqins(&src_head, que, sl);
- sl->addr = mcalloc(n + 1); /* +1 for zero termination */
+ dqrins(&src_head, que, sl);
+ sl->str.addr = mcalloc(n + 1); /* +1 for zero termination */
+ sl->str.len = n;
sl->line = source_line;
- memcpy(sl->addr, source_buffer, n + 1);
- } else
- {
+ memcpy(sl->str.addr, source_buffer, n + 1);
+ total_source_len += n;
+ }
+ if (creating_list_file && !(cmd_qlf.qlf & CQ_MACHINE_CODE))
+ { /* list now. for machine_code we intersperse machine code and M code, thus can't list M code yet */
+ NEWLINE_TO_NULL(source_buffer[n - 1]);
list_line_number();
list_line((char *)source_buffer);
}
}
+ NEWLINE_TO_NULL(source_buffer[n - 1]); /* compiler doesn't like trailing newlines (gives SPOREOL errors) */
TREF(source_error_found) = 0;
lb_init();
if (cmd_qlf.qlf & CQ_CE_PREPROCESS)
@@ -160,6 +169,18 @@ boolean_t compiler_startup(void)
* use for conversions or whatever are eliminated. Note the path is different in stp_gcol for
* the indirect stringpool which is only used during compilations.
*/
+ if (cmd_qlf.qlf & CQ_EMBED_SOURCE)
+ { /* Append source text to text pool */
+ ENSURE_STP_FREE_SPACE(total_source_len);
+ DBG_MARK_STRINGPOOL_UNEXPANDABLE;
+ TREF(routine_source_offset) = (uint4)(stringpool.free - stringpool.base);
+ dqloop(&src_head, que, sl)
+ {
+ str = sl->str;
+ s2pool(&str); /* changes str.addr, points it into stringpool */
+ }
+ DBG_MARK_STRINGPOOL_EXPANDABLE;
+ }
start_fetches(OC_NOOP);
resolve_blocks();
errknt = resolve_ref(errknt);
diff --git a/sr_port/cre_jnl_file.c b/sr_port/cre_jnl_file.c
index 2e7fc24..12df5fb 100644
--- a/sr_port/cre_jnl_file.c
+++ b/sr_port/cre_jnl_file.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -214,6 +214,8 @@ uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_
assert(0 == create_fn[create_fn_len]);
} else
{
+ if (NULL != info->csa)
+ cre_jnl_file_intrpt_rename(info->csa); /* deal with *_new.mjl files */
create_fn = &fn_buff[0];
if (SS_NORMAL != (info->status = prepare_unique_name((char *)info->jnl, (int)info->jnl_len, "", EXT_NEW,
(char *)create_fn, &create_fn_len, 0, &info->status2)))
@@ -350,6 +352,7 @@ uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_
/* We have already saved previous journal file name in info */
jfh_from_jnl_info(info, header);
header->recover_interrupted = mupip_jnl_recover;
+ header->last_eof_written = FALSE;
assert(ROUND_UP2(JNL_HDR_LEN, jnl_fs_block_size) == JNL_HDR_LEN);
assert((unsigned char *)header + JNL_HDR_LEN <= ARRAYTOP(hdr_base));
/* Although the real journal file header is REAL_JNL_HDR_LEN, we write the entire journal file header
@@ -473,6 +476,10 @@ uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_
F_CLOSE(channel, status); /* resets "channel" to FD_INVALID */
free(jrecbuf_base);
jrecbuf_base = NULL;
+# ifdef DEBUG
+ if (WBTEST_ENABLED(WBTEST_JNL_CREATE_FAIL))
+ return EXIT_ERR;
+# endif
if (info->no_rename)
return EXIT_NRM;
/* Say, info->jnl = a.mjl
diff --git a/sr_port/cre_jnl_file_intrpt_rename.c b/sr_port/cre_jnl_file_intrpt_rename.c
index 7055e26..2bc736b 100644
--- a/sr_port/cre_jnl_file_intrpt_rename.c
+++ b/sr_port/cre_jnl_file_intrpt_rename.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -26,18 +26,31 @@
#include "send_msg.h"
#include "gtmimagename.h"
-void cre_jnl_file_intrpt_rename(int fn_len, sm_uc_ptr_t fn)
+GBLREF gd_region *gv_cur_region;
+
+error_def(ERR_FILEPARSE);
+error_def(ERR_RENAMEFAIL);
+error_def(ERR_FILEDELFAIL);
+error_def(ERR_FILEDEL);
+error_def(ERR_FILERENAME);
+
+void cre_jnl_file_intrpt_rename(sgmnt_addrs *csa)
{
+ int fn_len;
+ sm_uc_ptr_t fn;
mstr filestr;
int status1, status2, ext_new_jnl_fn_len;
uint4 status, ustatus;
unsigned char ext_new_jnl_fn[MAX_FN_LEN];
- error_def(ERR_FILEPARSE);
- error_def(ERR_RENAMEFAIL);
- error_def(ERR_FILEDELFAIL);
- error_def(ERR_FILEDEL);
- error_def(ERR_FILERENAME);
+ assert(csa);
+ UNIX_ONLY(assert(csa->hdr)); /* csa->hdr may not be set, e.g. on VMS for MUPIP SET /JOURNAL */
+ /* We need either crit or standalone to ensure that there are no concurrent switch attempts. */
+ UNIX_ONLY(assert(csa->now_crit || (gv_cur_region && FILE_INFO(gv_cur_region)->grabbed_access_sem)));
+ if (!csa->hdr)
+ return;
+ fn = csa->hdr->jnl_file_name;
+ fn_len = csa->hdr->jnl_file_len;
filestr.addr = (char *)fn;
filestr.len = fn_len;
prepare_unique_name((char *)fn, fn_len, "", EXT_NEW, (char *)ext_new_jnl_fn, &ext_new_jnl_fn_len, 0, &ustatus);
@@ -46,9 +59,9 @@ void cre_jnl_file_intrpt_rename(int fn_len, sm_uc_ptr_t fn)
if (FILE_STAT_ERROR == status1)
{
if (IS_GTM_IMAGE)
- send_msg(VARLSTCNT(5) ERR_FILEPARSE, 2, filestr.len, filestr.addr, ustatus);
+ send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEPARSE, 2, filestr.len, filestr.addr, ustatus);
else
- gtm_putmsg(VARLSTCNT(5) ERR_FILEPARSE, 2, filestr.len, filestr.addr, ustatus);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEPARSE, 2, filestr.len, filestr.addr, ustatus);
return;
}
filestr.addr = (char *)ext_new_jnl_fn;
@@ -57,9 +70,9 @@ void cre_jnl_file_intrpt_rename(int fn_len, sm_uc_ptr_t fn)
if (FILE_STAT_ERROR == status2)
{
if (IS_GTM_IMAGE)
- send_msg(VARLSTCNT(5) ERR_FILEPARSE, 2, filestr.len, filestr.addr, ustatus);
+ send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEPARSE, 2, filestr.len, filestr.addr, ustatus);
else
- gtm_putmsg(VARLSTCNT(5) ERR_FILEPARSE, 2, filestr.len, filestr.addr, ustatus);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEPARSE, 2, filestr.len, filestr.addr, ustatus);
return;
}
if (FILE_NOT_FOUND == status1)
@@ -71,23 +84,25 @@ void cre_jnl_file_intrpt_rename(int fn_len, sm_uc_ptr_t fn)
{
if (IS_GTM_IMAGE)
{
- VMS_ONLY(send_msg(VARLSTCNT(8) ERR_RENAMEFAIL, 4, filestr.len, filestr.addr,
- fn_len, fn, status, ustatus);)
- UNIX_ONLY(send_msg(VARLSTCNT(7) ERR_RENAMEFAIL, 4, filestr.len, filestr.addr,
- fn_len, fn, status);)
+ VMS_ONLY(send_msg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_RENAMEFAIL, 4, filestr.len,
+ filestr.addr, fn_len, fn, status, ustatus));
+ UNIX_ONLY(send_msg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_RENAMEFAIL, 4, filestr.len,
+ filestr.addr, fn_len, fn, status));
} else
{
- VMS_ONLY(gtm_putmsg(VARLSTCNT(8) ERR_RENAMEFAIL, 4, filestr.len, filestr.addr,
- fn_len, fn, status, ustatus);)
- UNIX_ONLY(gtm_putmsg(VARLSTCNT(7) ERR_RENAMEFAIL, 4, filestr.len, filestr.addr,
- fn_len, fn, status);)
+ VMS_ONLY(gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_RENAMEFAIL, 4, filestr.len,
+ filestr.addr, fn_len, fn, status, ustatus));
+ UNIX_ONLY(gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_RENAMEFAIL, 4, filestr.len,
+ filestr.addr, fn_len, fn, status));
}
} else
{
if (IS_GTM_IMAGE)
- send_msg(VARLSTCNT(6) ERR_FILERENAME, 4, (int)filestr.len, filestr.addr, fn_len, fn);
+ send_msg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_FILERENAME, 4, (int)filestr.len, filestr.addr,
+ fn_len, fn);
else
- gtm_putmsg(VARLSTCNT(6) ERR_FILERENAME, 4, filestr.len, filestr.addr, fn_len, fn);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_FILERENAME, 4, filestr.len, filestr.addr,
+ fn_len, fn);
}
}
} else
@@ -99,21 +114,23 @@ void cre_jnl_file_intrpt_rename(int fn_len, sm_uc_ptr_t fn)
{
if (IS_GTM_IMAGE)
{
- VMS_ONLY(send_msg(VARLSTCNT(6) ERR_FILEDELFAIL, 2, filestr.len, filestr.addr,
- status, ustatus);)
- UNIX_ONLY(send_msg(VARLSTCNT(5) ERR_FILEDELFAIL, 2, filestr.len, filestr.addr, status);)
+ VMS_ONLY(send_msg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_FILEDELFAIL, 2, filestr.len,
+ filestr.addr, status, ustatus));
+ UNIX_ONLY(send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEDELFAIL, 2, filestr.len,
+ filestr.addr, status));
} else
{
- VMS_ONLY(gtm_putmsg(VARLSTCNT(6) ERR_FILEDELFAIL, 2, filestr.len, filestr.addr,
- status, ustatus);)
- UNIX_ONLY(gtm_putmsg(VARLSTCNT(5) ERR_FILEDELFAIL, 2, filestr.len, filestr.addr, status);)
+ VMS_ONLY(gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_FILEDELFAIL, 2, filestr.len,
+ filestr.addr, status, ustatus));
+ UNIX_ONLY(gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEDELFAIL, 2, filestr.len,
+ filestr.addr, status));
}
} else
{
if (IS_GTM_IMAGE)
- send_msg(VARLSTCNT(4) ERR_FILEDEL, 2, filestr.len, filestr.addr);
+ send_msg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_FILEDEL, 2, filestr.len, filestr.addr);
else
- gtm_putmsg(VARLSTCNT(4) ERR_FILEDEL, 2, filestr.len, filestr.addr);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_FILEDEL, 2, filestr.len, filestr.addr);
}
}
}
diff --git a/sr_port/cre_private_code_copy.c b/sr_port/cre_private_code_copy.c
index 57a3bcd..40fb748 100644
--- a/sr_port/cre_private_code_copy.c
+++ b/sr_port/cre_private_code_copy.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2002, 2013 Fidelity Information Services, Inc *
+ * Copyright 2002, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -39,17 +39,21 @@ uint4 cre_private_code_copy(rhdtyp *rtn)
int code_size;
#ifdef USHBIN_SUPPORTED
- assert(NULL != rtn->shlib_handle); /* don't need private copy if not shared */
- assert(NULL == rtn->shared_ptext_adr); /* if already private, we shouldn't be calling this routine */
+ assert(NULL != rtn->shared_ptext_adr); /* don't need private copy if not shared */
+ assert(rtn->shared_ptext_adr == rtn->ptext_adr); /* if already private, we shouldn't be calling this routine */
+
code_size = (int)(rtn->ptext_end_adr - rtn->ptext_adr) ;
ESTABLISH_RET(cre_priv_ch, UNIX_ONLY(ERR_MEMORY) VMS_ONLY(ERR_VMSMEMORY));
new_ptext = GTM_TEXT_ALLOC(code_size);
REVERT;
memcpy(new_ptext, rtn->ptext_adr, code_size);
adjust_frames(rtn->ptext_adr, rtn->ptext_end_adr, new_ptext);
- rtn->shared_ptext_adr = rtn->ptext_adr;
- rtn->ptext_adr = new_ptext;
- rtn->ptext_end_adr = new_ptext + code_size;
+ do
+ {
+ rtn->ptext_adr = new_ptext;
+ rtn->ptext_end_adr = new_ptext + code_size;
+ rtn = (rhdtyp *)rtn->old_rhead_adr;
+ } while (NULL != rtn);
inst_flush(new_ptext, code_size);
#endif
return SS_NORMAL;
diff --git a/sr_port/dbcertify.c b/sr_port/dbcertify.c
index 72401ec..4ad9704 100644
--- a/sr_port/dbcertify.c
+++ b/sr_port/dbcertify.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2005, 2012 Fidelity Information Services, Inc *
+ * Copyright 2005, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -51,10 +51,9 @@
#include "gtmimagename.h"
#include "error.h"
#include "iosp.h"
-#include "gtm_env_init.h"
#include "dbcertify.h"
#include "cli.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
#include "wbox_test_init.h"
@@ -79,8 +78,7 @@ int UNIX_ONLY(main)VMS_ONLY(dbcertify)(int argc, char **argv)
/* Initialization of scaffolding we run on */
GTM_THREADGBL_INIT;
- gtm_imagetype_init(DBCERTIFY_IMAGE);
- gtm_env_init();
+ common_startup_init(DBCERTIFY_IMAGE);
gtm_utf8_mode = FALSE; /* Only ever runs in V4 database so NO utf8 mode -- ever */
psa_gbl = malloc(SIZEOF(*psa_gbl));
memset(psa_gbl, 0, SIZEOF(*psa_gbl));
@@ -89,7 +87,6 @@ int UNIX_ONLY(main)VMS_ONLY(dbcertify)(int argc, char **argv)
VMS_ONLY(util_out_open(0));
VMS_ONLY(SET_EXIT_HANDLER(exi_blk, dbcertify_exit_handler, exi_condition)); /* Establish exit handler */
VMS_ONLY(ESTABLISH(dbcertify_base_ch));
- process_id = getpid();
/* Structure checks .. */
assert((24 * 1024) == SIZEOF(v15_sgmnt_data)); /* Verify V4 file header hasn't suddenly increased for some odd reason */
OPERATOR_LOG_MSG;
diff --git a/sr_port/deviceparameters.c b/sr_port/deviceparameters.c
index 96a5410..47393b9 100644
--- a/sr_port/deviceparameters.c
+++ b/sr_port/deviceparameters.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,14 +42,14 @@ LITDEF nametabent dev_param_names[] =
,{2,"BL*"} ,{4,"BLOC"}
,{4,"BU*"}
- ,{2,"CA"}, {4,"CANT*"}
+ ,{2,"CA"} ,{4,"CANT*"}
,{4,"CANO*"}
,{2,"CE*"}
,{3,"CHA*"}
,{3,"CHS*"}
,{3,"CLE*"}
,{3,"CLI"}
- ,{4,"COMM*"}, {7,"COMMAND"}
+ ,{4,"COMM*"} ,{7,"COMMAND"}
,{4,"CONN*"}
,{4,"CONT*"}
,{4,"CONV*"}
@@ -92,10 +92,15 @@ LITDEF nametabent dev_param_names[] =
,{3,"HOS*"} ,{4,"HOST"}
,{6,"ICHSET"}
+ ,{4,"IKEY"}
,{4,"INDE*"} ,{11,"INDEPENDENT"}
+ ,{8,"INREWIND"}
+ ,{6,"INSEEK"}
,{2,"IN*"} ,{4,"INSE"}
,{3,"IOE*"}
+ ,{3,"KEY"}
+
,{3,"LAB*"}
,{3,"LAS*"}
,{2,"LE*"} ,{4,"LENG"}
@@ -163,7 +168,10 @@ LITDEF nametabent dev_param_names[] =
,{1,"O"}
,{6,"OCHSET"}
+ ,{4,"OKEY"}
,{2,"OP*"}
+ ,{9,"OUTREWIND"}
+ ,{7,"OUTSEEK"}
,{2,"OV*"}
,{2,"OW*"}
@@ -200,6 +208,7 @@ LITDEF nametabent dev_param_names[] =
,{3,"RFM"}
,{1,"S"}
+ ,{3,"SEE*"}
,{3,"SEQ*"}
,{3,"SET*"}
,{2,"SH"} ,{3,"SHA*"} ,{4,"SHAR"}
@@ -208,7 +217,7 @@ LITDEF nametabent dev_param_names[] =
,{2,"SO*"}
,{3,"SPA*"}
,{3,"SPO*"}
- ,{2,"ST"} ,{3,"STR*"}
+ ,{2,"ST"} ,{3,"STR*"} ,{6,"STREAM"}
,{4,"STDE*"} ,{6,"STDERR"}
,{2,"SU*"}
,{2,"SY*"}
@@ -262,15 +271,18 @@ LITDEF nametabent dev_param_names[] =
,{4,"ZWID*"}
,{4,"ZWRA*"}
};
-/* Offset of letter in dev_param_names */
+/* Offset of letter in dev_param_names */
LITDEF uint4 dev_param_index[27] =
{
/* A B C D E F G H I J K L M N */
- 0, 5, 9, 26, 34, 49, 64, 66, 70, 76, 76, 76, 84, 87,
+ 0, 5, 9, 26, 34, 49, 64, 66, 70, 79, 79, 80, 88, 91,
+
+
/* O P Q R S T U V W X Y Z end */
- 153, 158, 177, 178, 191, 209, 219, 225, 226, 241, 242, 243, 257
+ 157, 165, 184, 185, 198, 218, 228, 234, 235, 250, 251, 252, 266
};
+
/* Offset of string within letter in dev_param_names */
/* maintained in conjunction with zshow_params.h = offset in letter, letter */
LITDEF zshow_index zshow_param_index[] =
@@ -280,15 +292,15 @@ LITDEF zshow_index zshow_param_index[] =
/* FIL FIXED FOLLOW */
{5,5}, {8,5}, {14,5},
/* HOST ICHSET INDEPENDENT INSE LAB */
- {3,7}, {0,8}, {2,8}, {4,8}, {1,11},
+ {3,7}, {0,8}, {2,8}, {7,8}, {1,11},
/* LENG NOCENE NODEST NOECHO NOEDIT NOEMPTERM NOESCA NOFOLLOW NOHOST NOINSE */
{3,11}, {7,13}, {10,13}, {15,13}, {17,13}, {19,13}, {21,13}, {27,13}, {31,13}, {33,13},
/* NOPAST NOREADS NOTTSY NOTYPE NOWRAP OCHSET PAD PARSE PAST PRMMBX RCHK */
{39,13}, {44,13}, {55,13}, {57,13}, {63,13}, {1,14}, {8,15}, {11,15}, {13,15}, {17,15}, {1,17},
-/* READ READS REC SHAR SHELL STDERR TERM TTSY TYPE UIC WAIT WCHK */
- {2,17}, {4,17}, {5,17}, {5,18}, {7,18}, {15,18}, {1,19}, {7,19}, {9,19}, {1,20}, {2,22}, {4,22},
-/* WIDTH WRITE */
- {6,22}, {10,22}
+/* READ READS REC SHAR SHELL STDERR STREAM TERM TTSY TYPE UIC */
+ {2,17}, {4,17}, {5,17}, {6,18}, {8,18}, {17,18}, {15,18}, {1,19}, {7,19}, {9,19}, {1,20},
+/* WAIT WCHK WIDTH WRITE */
+ {2,22}, {4,22}, {6,22}, {10,22}
};
int deviceparameters(oprtype *c, char who_calls)
@@ -366,10 +378,15 @@ int deviceparameters(oprtype *c, char who_calls)
,iop_hostsync, iop_hostsync
,iop_ipchset
+ ,iop_input_key
,iop_independent ,iop_independent
+ ,iop_inrewind
+ ,iop_inseek
,iop_insert ,iop_insert
,iop_ioerror
+ ,iop_key
+
,iop_label
,iop_lastpage
,iop_length ,iop_length
@@ -437,7 +454,10 @@ int deviceparameters(oprtype *c, char who_calls)
,iop_o_protection
,iop_opchset
+ ,iop_output_key
,iop_operator
+ ,iop_outrewind
+ ,iop_outseek
,iop_noinsert
,iop_o_protection
@@ -474,6 +494,7 @@ int deviceparameters(oprtype *c, char who_calls)
,iop_rfm
,iop_s_protection
+ ,iop_seek
,iop_sequential
,iop_setup
,iop_shared ,iop_shared, iop_shared
@@ -482,7 +503,7 @@ int deviceparameters(oprtype *c, char who_calls)
,iop_socket
,iop_space
,iop_spool
- ,iop_stream, iop_stream
+ ,iop_stream, iop_stream, iop_stream
,iop_stderr, iop_stderr
,iop_submit
,iop_s_protection
diff --git a/sr_port/do_xform.h b/sr_port/do_xform.h
index 345bac2..46e48f1 100644
--- a/sr_port/do_xform.h
+++ b/sr_port/do_xform.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,6 +24,7 @@
*/ \
OUTPUT->len = 0; \
*LENGTH = 0; \
+ return; \
} \
}
diff --git a/sr_port/dse.h b/sr_port/dse.h
index a942eb3..63d54e8 100644
--- a/sr_port/dse.h
+++ b/sr_port/dse.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,13 +14,17 @@
error_def(ERR_DSEWCREINIT);
-#define PATCH_SAVE_SIZE 128
+#define BADDSEBLK (block_id)-1
#define DSE_DMP_TIME_FMT "DD-MON-YEAR 24:60:SS"
+#define DSEBLKCUR TRUE
+#define DSEBLKNOCUR FALSE
+#define DSEBMLOK FALSE
+#define DSENOBML TRUE
+#define PATCH_SAVE_SIZE 128
#define SPAN_START_BYTE 0x02
#define SPAN_BYTE_MAX 255
#define SPAN_BYTE_MIN 1
-
#define GET_CURR_TIME_IN_DOLLARH_AND_ZDATE(dollarh_mval, dollarh_buffer, zdate_mval, zdate_buffer) \
{ /* gets current time in the mval "dollarh_mval" in dollarh format and in the mval "zdate_mval" in ZDATE format \
* the ZDATE format string used is DSE_DMP_TIME_FMT \
@@ -133,58 +137,142 @@ enum dse_fmt
send_msg_csa(CSA_ARG(CS_ADDRS) VARLSTCNT(4) ERR_DSEWCREINIT, 2, DB_LEN_STR(gv_cur_region)); \
}
-void dse_ctrlc_setup(void);
-int dse_data(char *dst, int *len);
-int dse_getki(char *dst, int *len, char *qual, int qual_len);
-int dse_is_blk_in(sm_uc_ptr_t rp, sm_uc_ptr_t r_top, short size);
-int dse_ksrch(block_id srch, block_id_ptr_t pp, int4 *off, char *targ_key, int targ_len);
-int dse_key_srch(block_id srch, block_id_ptr_t pp, int4 *off, char *targ_key, int targ_len);
-int dse_order(block_id srch, block_id_ptr_t pp, int4 *op, char *targ_key, short int targ_len, bool dir_data_blk);
-void dse_rmsb(void);
-void dse_ctrlc_handler(int sig);
-void dse_exhaus(int4 pp, int4 op);
-void dse_m_rest(block_id blk, unsigned char *bml_list, int4 bml_size, sm_vuint_ptr_t blks_ptr, bool in_dir_tree);
-void dse_rmrec(void);
-void dse_find_roots(block_id index);
-boolean_t dse_fdmp(sm_uc_ptr_t data, int len);
-boolean_t dse_fdmp_output(void *addr, int4 len);
-void dse_adrec(void);
-void dse_adstar(void);
-void dse_all(void);
-boolean_t dse_b_dmp(void);
-void dse_cache(void);
-void dse_chng_bhead(void);
-void dse_chng_fhead(void);
-void dse_chng_rhead(void);
-void dse_crit(void);
-void dse_dmp(void);
-void dse_eval(void);
-void dse_f_blk(void);
-void dse_f_free(void);
-void dse_f_key(void);
-void dse_f_reg(void);
-void dse_flush(void);
-int parse_dlr_char(char *src, char *top, char *dlr_subsc);
-void dse_help(void);
-void dse_version(void);
-void dse_integ(void);
-bool dse_is_blk_free (block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr);
-int4 dse_lm_blk_free(int4 blk, sm_uc_ptr_t base_addr);
-void dse_maps(void);
-void dse_open (void);
-void dse_close(void);
-void dse_over(void);
-void dse_page(void);
-boolean_t dse_r_dmp(void);
-void dse_range(void);
-void dse_rest(void);
-void dse_save(void);
-void dse_shift(void);
-void dse_wcreinit (void);
-sm_uc_ptr_t dump_record(sm_uc_ptr_t rp, block_id blk, sm_uc_ptr_t bp, sm_uc_ptr_t b_top);
-void dse_dmp_fhead (void);
-void dse_ctrlc_handler(int sig);
-void dse_remove(void);
-gv_namehead *dse_find_gvt(gd_region *reg, char *name, int name_len);
+/* This macro is currently used only inside the BUILD_AIMG_IF_JNL_ENABLED_AND_T_END_WITH_EFFECTIVE_TN macro */
+#ifdef GTM_CRYPT
+#define BUILD_ENCRYPT_TWINBUFF_IF_NEEDED(CSA, CSD, TN) \
+{ \
+ blk_hdr_ptr_t bp, save_bp; \
+ gd_segment *seg; \
+ int gtmcrypt_errno, req_enc_blk_size; \
+ \
+ GBLREF gd_region *gv_cur_region; \
+ \
+ if (CSD->is_encrypted && (TN < CSA->ti->curr_tn)) \
+ { /* BG and db encryption is enabled and the DSE update caused the block-header to potentially have a tn \
+ * that is LESS than what it had before. At this point, the global buffer (corresponding to blkhist.blk_num) \
+ * reflects the contents of the block AFTER the dse update (bg_update would have touched this) whereas \
+ * the corresponding encryption global buffer reflects the contents of the block BEFORE the update. \
+ * Normally wcs_wtstart takes care of propagating the tn update from the regular global buffer to the \
+ * corresponding encryption buffer. But if before it gets a chance, let us say a process goes to t_end \
+ * as part of a subsequent transaction and updates this same block. Since the blk-hdr-tn potentially \
+ * decreased, it is possible that the PBLK writing check (comparing blk-hdr-tn with the epoch_tn) decides \
+ * to write a PBLK for this block (even though a PBLK was already written for this block as part of a \
+ * previous DSE CHANGE -BL -TN in the same epoch). In this case, since the db is encrypted, the logic \
+ * will assume there were no updates to this block since the last time wcs_wtstart updated the encryption \
+ * buffer and therefore use that to write the pblk, which is incorrect since it does not yet contain the \
+ * tn update. The consequence of this is would be writing an older before-image PBLK) record to the \
+ * journal file. To prevent this situation, we update the encryption buffer here (before releasing crit) \
+ * using logic like that in wcs_wtstart to ensure it is in sync with the regular global buffer. To ensure \
+ * that t_end doesn't release crit, we set CSA->hold_onto_crit to TRUE \
+ * Note: \
+ * Although we use cw_set[0] to access the global buffer corresponding to the block number being updated, \
+ * cw_set_depth at this point is 0 because t_end resets it. This is considered safe since cw_set is a \
+ * static array (as opposed to malloc'ed memory) and hence is always available and valid until it gets \
+ * overwritten by subsequent updates. \
+ */ \
+ bp = (blk_hdr_ptr_t)GDS_ANY_REL2ABS(CSA, cw_set[0].cr->buffaddr); \
+ DBG_ENSURE_PTR_IS_VALID_GLOBUFF(CSA, CSD, (sm_uc_ptr_t)bp); \
+ save_bp = (blk_hdr_ptr_t)GDS_ANY_ENCRYPTGLOBUF(bp, CSA); \
+ DBG_ENSURE_PTR_IS_VALID_ENCTWINGLOBUFF(CSA, CSD, (sm_uc_ptr_t)save_bp); \
+ assert((bp->bsiz <= CSD->blk_size) && (bp->bsiz >= SIZEOF(*bp))); \
+ req_enc_blk_size = MIN(CSD->blk_size, bp->bsiz) - SIZEOF(*bp); \
+ if (BLK_NEEDS_ENCRYPTION(bp->levl, req_enc_blk_size)) \
+ { \
+ ASSERT_ENCRYPTION_INITIALIZED; \
+ memcpy(save_bp, bp, SIZEOF(blk_hdr)); \
+ GTMCRYPT_ENCRYPT(CSA, CSA->encr_key_handle, (char *)(bp + 1), req_enc_blk_size, \
+ (char *)(save_bp + 1), gtmcrypt_errno); \
+ if (0 != gtmcrypt_errno) \
+ { \
+ seg = gv_cur_region->dyn.addr; \
+ GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, gtm_putmsg, seg->fname_len, seg->fname); \
+ } \
+ } else \
+ memcpy(save_bp, bp, bp->bsiz); \
+ } \
+}
+#else
+#define BUILD_ENCRYPT_TWINBUFF_IF_NEEDED(CSA, CSD, TN)
+#endif
+
+/* This macro is used whenever t_end needs to be invoked with a 3rd parameter != TN_NOT_SPECIFIED.
+ * Currently the only two usages of this are from DSE and hence this macro is placed in dse.h.
+ */
+#define BUILD_AIMG_IF_JNL_ENABLED_AND_T_END_WITH_EFFECTIVE_TN(CSA, CSD, CTN, HIST) \
+{ \
+ trans_num cTn; \
+ boolean_t was_hold_onto_crit; \
+ \
+ GBLREF gd_region *gv_cur_region; \
+ GBLREF boolean_t unhandled_stale_timer_pop; \
+ GBLREF sgmnt_addrs *cs_addrs; \
+ \
+ cTn = CTN; \
+ assert(CSA == cs_addrs); \
+ BUILD_AIMG_IF_JNL_ENABLED(CSD, cTn); \
+ was_hold_onto_crit = CSA->hold_onto_crit; \
+ CSA->hold_onto_crit = TRUE; /* need this so t_end doesn't release crit (see below comment for why) */ \
+ t_end(HIST, NULL, cTn); \
+ BUILD_ENCRYPT_TWINBUFF_IF_NEEDED(CSA, CSD, cTn); \
+ CSA->hold_onto_crit = was_hold_onto_crit; \
+ if (!was_hold_onto_crit) \
+ rel_crit(gv_cur_region); \
+ if (unhandled_stale_timer_pop) \
+ process_deferred_stale(); \
+}
+
+void dse_adrec(void);
+void dse_adstar(void);
+void dse_all(void);
+boolean_t dse_b_dmp(void);
+void dse_cache(void);
+void dse_chng_bhead(void);
+void dse_chng_fhead(void);
+void dse_chng_rhead(void);
+void dse_close(void);
+void dse_crit(void);
+void dse_ctrlc_handler(int sig);
+void dse_ctrlc_setup(void);
+int dse_data(char *dst, int *len);
+void dse_dmp(void);
+void dse_dmp_fhead (void);
+void dse_eval(void);
+void dse_exhaus(int4 pp, int4 op);
+void dse_f_blk(void);
+void dse_f_free(void);
+void dse_f_key(void);
+void dse_f_reg(void);
+boolean_t dse_fdmp(sm_uc_ptr_t data, int len);
+boolean_t dse_fdmp_output(void *addr, int4 len);
+gv_namehead *dse_find_gvt(gd_region *reg, char *name, int name_len);
+void dse_find_roots(block_id index);
+void dse_flush(void);
+block_id dse_getblk(char *element, boolean_t nobml, boolean_t carry_curr);
+int dse_getki(char *dst, int *len, char *qual, int qual_len);
+void dse_help(void);
+void dse_integ(void);
+boolean_t dse_is_blk_free(block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr);
+int dse_is_blk_in(sm_uc_ptr_t rp, sm_uc_ptr_t r_top, short size);
+int dse_key_srch(block_id srch, block_id_ptr_t pp, int4 *off, char *targ_key, int targ_len);
+int dse_ksrch(block_id srch, block_id_ptr_t pp, int4 *off, char *targ_key, int targ_len);
+int4 dse_lm_blk_free(int4 blk, sm_uc_ptr_t base_addr);
+void dse_m_rest(block_id blk, unsigned char *bml_list, int4 bml_size, sm_vuint_ptr_t blks_ptr, bool in_dir_tree);
+void dse_maps(void);
+void dse_open (void);
+int dse_order(block_id srch, block_id_ptr_t pp, int4 *op, char *targ_key, short int targ_len, bool dir_data_blk);
+void dse_over(void);
+void dse_page(void);
+boolean_t dse_r_dmp(void);
+void dse_range(void);
+void dse_remove(void);
+void dse_rest(void);
+void dse_rmrec(void);
+void dse_rmsb(void);
+void dse_save(void);
+void dse_shift(void);
+void dse_version(void);
+void dse_wcreinit (void);
+sm_uc_ptr_t dump_record(sm_uc_ptr_t rp, block_id blk, sm_uc_ptr_t bp, sm_uc_ptr_t b_top);
+int parse_dlr_char(char *src, char *top, char *dlr_subsc);
#endif
diff --git a/sr_port/dse.hlp b/sr_port/dse.hlp
index 84019f7..3b0c3c1 100644
--- a/sr_port/dse.hlp
+++ b/sr_port/dse.hlp
@@ -1165,7 +1165,8 @@
the CACHE command is:
CA[CHE] -ALL
- -RE[COVER
+ -RE[COVER]
+ -SH[OW]
-VE[RIFY]
3 Qualifiers
@@ -1180,6 +1181,13 @@
o Attempt DSE -RECOVER only if a DSE CACHE -VERIFY commands reports the
cache is "NOT clean".
+ -SH[OW]
+
+ Displays the cache data structure information. All values are in 8-byte
+ hexadecimal form. If the database has encryption turned on, SHOW
+ additionally displays an element that gives information about the
+ encrypted global buffer section in shared memory.
+
-VE[RIFY] [-ALL]
Verifies the integrity of the cache data structures as well as the
@@ -1220,6 +1228,29 @@
This command reinitializes the cache data structures of the current region
and reverts the cache of a database having BG access to "clean" state.
+ Example:
+
+ DSE> CACHE -SHOW
+ File /home/jdoe/node1/areg.dat
+ Region AREG
+
+ Region AREG : Shared_memory = 0x00002B6845040000
+ Region AREG : node_local = 0x0000000000000000
+ Region AREG : critical = 0x0000000000010000
+ Region AREG : shmpool_buffer = 0x0000000000023000
+ Region AREG : lock_space = 0x0000000000125000
+ Region AREG : cache_queues_state = 0x000000000012A000
+ Region AREG : cache_que_header = 0x000000000012A030 : Numelems = 0x00000407 : Elemsize = 0x00000098
+ Region AREG : cache_record = 0x0000000000150458 : Numelems = 0x00000400 : Elemsize = 0x00000098
+ Region AREG : global_buffer = 0x0000000000177000 : Numelems = 0x00000400 : Elemsize = 0x00000400
+ Region AREG : db_file_header = 0x0000000000277000
+ Region AREG : bt_que_header = 0x00000000002B7000 : Numelems = 0x00000407 : Elemsize = 0x00000040
+ Region AREG : th_base = 0x00000000002C71D0
+ Region AREG : bt_record = 0x00000000002C7200 : Numelems = 0x00000400 : Elemsize = 0x00000040
+ Region AREG : shared_memory_size = 0x00000000002D8000
+
+ DSE>
+
2 CLose
CLose
@@ -1466,15 +1497,17 @@
This command displays an output like the following:
- File /home/gtmuser1/mumps.dat
- Region DEFAULT
+ File /home/jdoe/.fis-gtm/V6.1-000_x86_64/g/gtm.dat
+ Region DEFAULT
- Date/Time 27-OCT-2009 04:25:12 [$H = 61661,15912]
+ File /home/jdoe/.fis-gtm/V6.1-000_x86_64/g/gtm.dat
+ Region DEFAULT
+ Date/Time 27-JAN-2014 03:13:40 [$H = 63214,11620]
Access method BG Global Buffers 1024
Reserved Bytes 0 Block size (in bytes) 1024
- Maximum record size 256 Starting VBN 129
- Maximum key size 64 Total blocks 0x00000191
- Null subscripts NEVER Free blocks 0x0000002A
+ Maximum record size 256 Starting VBN 513
+ Maximum key size 64 Total blocks 0x000000C9
+ Null subscripts NEVER Free blocks 0x00000056
Standard Null Collation FALSE Free space 0x00000000
Last Record Backup 0x0000000000000001 Extension Count 100
Last Database Backup 0x0000000000000001 Number of local maps 1
@@ -1482,27 +1515,28 @@
In critical section 0x00000000 Timers pending 0
Cache freeze id 0x00000000 Flush timer 00:00:01:00
Freeze match 0x00000000 Flush trigger 960
- Current transaction 0x0000000000007539 No. of writes/flush 7
- Maximum TN 0xFFFFFFFFE3FFFFFF Certified for Upgrade to V5
- Maximum TN Warn 0xFFFFFFFF73FFFFFF Desired DB Format V5
- Master Bitmap Size 112 Blocks to Upgrade 0x00000000
+ Current transaction 0x0000000000002712 No. of writes/flush 7
+ Maximum TN 0xFFFFFFFF83FFFFFF Certified for Upgrade to V6
+ Maximum TN Warn 0xFFFFFFFD93FFFFFF Desired DB Format V6
+ Master Bitmap Size 496 Blocks to Upgrade 0x00000000
Create in progress FALSE Modified cache blocks 0
Reference count 1 Wait Disk 0
Journal State [inactive] ON Journal Before imaging TRUE
- Journal Allocation 100 Journal Extension 100
- Journal Buffer Size 128 Journal Alignsize 128
- Journal AutoSwitchLimit 8388600 Journal Epoch Interval 30
- Journal Yield Limit 8 Journal Sync IO TRUE
- Journal File: /home/gtmuser1/mumps.mjl
+ Journal Allocation 2048 Journal Extension 2048
+ Journal Buffer Size 2308 Journal Alignsize 4096
+ Journal AutoSwitchLimit 8386560 Journal Epoch Interval 30
+ Journal Yield Limit 8 Journal Sync IO FALSE
+ Journal File: /home/jdoe/.fis-gtm/V6.1-000_x86_64/g/gtm.mjl
Mutex Hard Spin Count 128 Mutex Sleep Spin Count 128
- Mutex Spin Sleep Time 2048 KILLs in progress 0
+ Mutex Queue Slots 1024 KILLs in progress 0
Replication State OFF Region Seqno 0x0000000000000001
Zqgblmod Seqno 0x0000000000000000 Zqgblmod Trans 0x0000000000000000
- Endian Format LITTLE Commit Wait Spin Count 17
- Database file encrypted FALSE
+ Endian Format LITTLE Commit Wait Spin Count 16
+ Database file encrypted FALSE Inst Freeze on Error FALSE
+ Spanning Node Absent TRUE Maximum Key Size Assured TRUE
Note that the certain fileheader elements appear depending on the current
- state of database. For example, as Journaling is not enabled in the
+ state of database. For example, if Journaling is not enabled in the
database, DSE does not display Journal data element fields.
Example:
@@ -1645,7 +1679,8 @@
-F[REEBLOCK]
- Finds the nearest free block to the block specified by -HINT.
+ Finds the nearest free block to the block specified by -HINT. FREEBLOCK
+ accepts bit maps as starting or ending points.
o The -FREEBLOCK qualifier is incompatible with all other qualifiers
except -BLOCK and -HINT.
@@ -1850,7 +1885,7 @@
-BU[SY]
Marks the current block as busy in the block's local map and appropriately
- updates the master bitmap.
+ updates the master bitmap. BUSY accepts bit map blocks.
Compatible only with: -BLOCK
@@ -1864,7 +1899,8 @@
-M[ASTER]
Sets the bit in the master bitmap associated with the current block's
- local map according to whether or not that local map is full.
+ local map according to whether or not that local map is full. MASTER
+ accepts bit map blocks.
Use only with: -BLOCK.
@@ -2064,14 +2100,16 @@
-F[ROM]=block_number
- Specifies a starting block number for the range search.
+ Specifies a starting block number for the range search. DSE RANGE accept
+ bit maps as starting or ending points.
By default, RANGE starts processing at the beginning of the file.
-T[O]=block-number
- Specifies an ending block number for the range search. By default, RANGE
- stops processing at the end of the file.
+ Specifies an ending block number for the range search. DSE RANGE accept
+ bit maps as starting or ending points. By default, RANGE stops processing
+ at the end of the file.
-I[NDEX]
@@ -2177,6 +2215,11 @@
a DSE operation. When no block has been accessed, that is, on the first
block-oriented command, DSE uses block one (1).
+ BLOCK accepts blocks higher than the current database size because they
+ deal with set of saved block copies rather than the database and there are
+ situations where a saved block may be outside the current database size
+ (for example, due to a concurrent MUPIP REORG -TRUNCATE).
+
-C[OUNT]=count
Specifies the number of records to remove.
@@ -2207,6 +2250,9 @@
-VERSION is required to REMOVE a SAVE buffer. -VERSION is incompatible
with all qualifiers except -BLOCK.
+ If there is only one version of the specified -BLOCK= block in the current
+ region, DSE REMOVE defaults to that version.
+
Use only with: -BLOCK; decimal
2 REStore
@@ -2214,10 +2260,10 @@
The RESTORE command restores saved versions of blocks.
- RES[TORE] B[LOCK]=block-number
- F[ROM]=from
- R[EGION]=region
- V[ERSION]=version-number
+ RES[TORE] -B[LOCK]=block-number
+ -F[ROM]=from
+ -R[EGION]=region
+ -V[ERSION]=version-number
The version number is specified in decimal.
@@ -2232,12 +2278,19 @@
a DSE operation. When no block has been accessed, (i.e., on the first
block-oriented command), DSE uses block one (1).
+ BLOCK accepts blocks higher than the current database size because it deal
+ with set of saved block copies rather than the database and there are
+ situations where a saved block may be outside the current database size
+ (for example, due to a concurrent MUPIP REORG -TRUNCATE).
+
-F[ROM]=block_number
Specifies the block number of the SAVE buffer to restore.
DSE restores the block specified with -BLOCK qualifier with the block
- specified by the -FROM qualifier.
+ specified by the -FROM qualifier. If there is only one version of the
+ specified -FROM= block, DSE RESTORE defaults to that version and it always
+ restores the original block transaction number.
By default, RESTORE uses the target block number as the -FROM block
number.
@@ -2296,6 +2349,11 @@
By default, SAVE -LIST provides a directory of all SAVEd blocks.
+ LIST displays blocks higher than the current database size because it
+ deals with set of saved block copies rather than the database and there
+ are situations where a saved block may be outside the current database
+ size (for example, due to a concurrent MUPIP REORG -TRUNCATE);
+
Incompatible with: -COMMENT
-[NO]C[RIT]
@@ -2311,6 +2369,7 @@
zeros, or shortening the block. The format of the SHIFT command is:
SH[IFT] -B[ACKWARD]=b_shift
+ -BL[OCK]=block_number
-F[ORWARD]=f_shift
-O[FFSET]=offset
@@ -2329,6 +2388,10 @@
Incompatible with: -FORWARD
+ -BL[OCK]=block_number
+
+ Specifies the block number to perform the DSE SHIFT.
+
-F[ORWARD]=shift
Specifies the number of bytes to shift data toward the end of the block.
@@ -2780,7 +2843,7 @@
1 Copyright
Copyright
- Copyright 2013
+ Copyright 2014
Fidelity Information Services, Inc. All rights reserved.
@@ -2801,7 +2864,7 @@
**Note**
- This help file is a concise representation of revision V6.1-000 of the
+ This help file is a concise representation of revision V6.2-000 of the
UNIX Administration and Operations Guide. To obtain a copy of the current
revision, go to www.fis-gtm.com and then click on the User Documentation
tab.
diff --git a/sr_port/dse_adrec.c b/sr_port/dse_adrec.c
index fc579d2..0e55bcf 100644
--- a/sr_port/dse_adrec.c
+++ b/sr_port/dse_adrec.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -37,18 +37,18 @@
#include "gvcst_blk_build.h"
#include "util.h"
#include "t_abort.h"
+#include "gtmmsg.h"
-GBLREF char *update_array, *update_array_ptr;
-GBLREF uint4 update_array_size;
-GBLREF srch_hist dummy_hist;
-GBLREF block_id patch_curr_blk;
+GBLREF char patch_comp_key[MAX_KEY_SZ + 1], *update_array, *update_array_ptr;
+GBLREF cw_set_element cw_set[];
+GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF char patch_comp_key[MAX_KEY_SZ + 1];
-GBLREF unsigned short patch_comp_count;
-GBLREF gd_region *gv_cur_region;
-GBLREF cw_set_element cw_set[];
+GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF srch_hist dummy_hist;
+GBLREF uint4 update_array_size;
+GBLREF unsigned short patch_comp_count;
+error_def(ERR_AIMGBLKFAIL);
error_def(ERR_CPBEYALLOC);
error_def(ERR_DBRDONLY);
error_def(ERR_DSEBLKRDFAIL);
@@ -58,32 +58,24 @@ error_def(ERR_REC2BIG);
void dse_adrec(void)
{
+ block_id blk, blk_ptr;
+ blk_segment *bs1, *bs_ptr;
char data[MAX_LINE], key[MAX_KEY_SZ + 1];
- unsigned short cc;
- int tmp_cmpc;
- sm_uc_ptr_t new_bp, lbp, b_top, rp, r_top, key_top;
- short int size, new_len, rsize;
int data_len, key_len;
int4 blk_seg_cnt, blk_size;
- block_id blk;
- blk_segment *bs1, *bs_ptr;
+ short int new_len, rsize, size;
+ sgmnt_addrs *csa;
+ sm_uc_ptr_t b_top, key_top, lbp, new_bp, rp, r_top;
srch_blk_status blkhist;
+ unsigned short cc;
- if (gv_cur_region->read_only)
- rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
+ csa = cs_addrs;
+ if (gv_cur_region->read_only)
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- if(!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- patch_curr_blk = blk;
- }
- if (patch_curr_blk < 0 || patch_curr_blk >= cs_addrs->ti->total_blks || !(patch_curr_blk % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSENOBML, DSEBLKCUR))) /* WARNING: assignment */
return;
- }
- if (cli_present("KEY") != CLI_PRESENT)
+ if (CLI_PRESENT != cli_present("KEY"))
{
util_out_print("Error: key must be specified.", TRUE);
return;
@@ -91,90 +83,84 @@ void dse_adrec(void)
if (!dse_getki(&key[0], &key_len, LIT_AND_LEN("KEY")))
return;
t_begin_crit(ERR_DSEFAIL);
- blk_size = cs_addrs->hdr->blk_size;
- blkhist.blk_num = patch_curr_blk;
+ blk_size = csa->hdr->blk_size;
+ blkhist.blk_num = blk;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
- rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
-
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
lbp = (uchar_ptr_t)malloc(blk_size);
memcpy(lbp, blkhist.buffaddr, blk_size);
-
if (((blk_hdr_ptr_t)lbp)->bsiz > blk_size)
((blk_hdr_ptr_t)lbp)->bsiz = blk_size;
else if (((blk_hdr_ptr_t)lbp)->bsiz < SIZEOF(blk_hdr))
((blk_hdr_ptr_t)lbp)->bsiz = SIZEOF(blk_hdr);
-
b_top = lbp + ((blk_hdr_ptr_t)lbp)->bsiz;
if (((blk_hdr_ptr_t)lbp)->levl)
{
- if (cli_present("POINTER") != CLI_PRESENT)
+ if (CLI_PRESENT != cli_present("POINTER"))
{
util_out_print("Error: block pointer must be specified for this index block record.", TRUE);
+ t_abort(gv_cur_region, csa);
free(lbp);
- t_abort(gv_cur_region, cs_addrs);
return;
}
- if (!cli_get_hex("POINTER", (uint4 *)&blk))
+ if (BADDSEBLK == (blk_ptr = dse_getblk("POINTER", DSENOBML, DSEBLKNOCUR))) /* WARNING: assignment */
{
- t_abort(gv_cur_region, cs_addrs);
+ t_abort(gv_cur_region, csa);
free(lbp);
return;
}
- if (blk < 0 || blk >= cs_addrs->ti->total_blks || !(blk % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: pointer is an invalid block number.", TRUE);
- free(lbp);
- t_abort(gv_cur_region, cs_addrs);
- return;
- }
- MEMCP(&data[0], (char *)&blk, 0, SIZEOF(block_id), SIZEOF(block_id));
+ MEMCP(&data[0], (char *)&blk_ptr, 0, SIZEOF(block_id), SIZEOF(block_id));
data_len = SIZEOF(block_id);
} else
{
- if (cli_present("DATA") != CLI_PRESENT)
+ if (CLI_PRESENT != cli_present("DATA"))
{
util_out_print("Error: data must be specified for this data block record.", TRUE);
+ t_abort(gv_cur_region, csa);
free(lbp);
- t_abort(gv_cur_region, cs_addrs);
return;
}
if (FALSE == dse_data(&data[0], &data_len))
- {
+ { /* dse_data return of FALSE means cli_parse already issued an error */
+ t_abort(gv_cur_region, csa);
free(lbp);
- t_abort(gv_cur_region, cs_addrs);
return;
}
- if (key_len + data_len > cs_addrs->hdr->max_rec_size)
+ if (key_len + data_len > csa->hdr->max_rec_size)
{
- rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(10) ERR_REC2BIG, 4, key_len + data_len,
- (int4)cs_addrs->hdr->max_rec_size, REG_LEN_STR(gv_cur_region), ERR_GVIS, 2, LEN_AND_STR(key));
+ t_abort(gv_cur_region, csa);
+ free(lbp);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(10) ERR_REC2BIG, 4, key_len + data_len,
+ (int4)csa->hdr->max_rec_size, REG_LEN_STR(gv_cur_region), ERR_GVIS, 2, LEN_AND_STR(key));
}
-
}
- if (cli_present("RECORD") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("RECORD"))
{
if (!(rp = skan_rnum(lbp, TRUE)))
- {
+ { /* a FALSE return from skan_rnum means either a cli parser problem or a record beyond the end of the block
+ * both of which cause output
+ */
+ t_abort(gv_cur_region, csa);
free(lbp);
- t_abort(gv_cur_region, cs_addrs);
return;
}
- } else if (cli_present("OFFSET") == CLI_PRESENT)
+ } else if (CLI_PRESENT == cli_present("OFFSET"))
{
if (!(rp = skan_offset(lbp, TRUE)))
- {
+ { /* a FALSE return from skan_rnum means either a cli parser problem or an offset beyond the end of the block
+ * both of which cause output
+ */
+ t_abort(gv_cur_region, csa);
free(lbp);
- t_abort(gv_cur_region, cs_addrs);
return;
}
} else
{
util_out_print("Error: must specify a record number or offset for the record to be added.", TRUE);
+ t_abort(gv_cur_region, csa);
free(lbp);
- t_abort(gv_cur_region, cs_addrs);
return;
}
-
new_bp = (uchar_ptr_t)malloc(blk_size);
size = (key_len < patch_comp_count) ? key_len : patch_comp_count;
for (cc = 0; cc < size && patch_comp_key[cc] == key[cc]; cc++)
@@ -225,28 +211,26 @@ void dse_adrec(void)
if (rp - lbp + new_len > blk_size)
{
util_out_print("Error: record too large for remaining space in block.", TRUE);
+ t_abort(gv_cur_region, csa);
free(lbp);
free(new_bp);
- t_abort(gv_cur_region, cs_addrs);
return;
}
memcpy(rp, new_bp, new_len);
free(new_bp);
((blk_hdr_ptr_t)lbp)->bsiz += new_len + (unsigned int)(rp - b_top);
-
BLK_INIT(bs_ptr, bs1);
BLK_SEG(bs_ptr, (uchar_ptr_t)lbp + SIZEOF(blk_hdr), (int)((blk_hdr_ptr_t)lbp)->bsiz - SIZEOF(blk_hdr));
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.", TRUE);
+ t_abort(gv_cur_region, csa);
free(lbp);
- t_abort(gv_cur_region, cs_addrs);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, blk, DB_LEN_STR(gv_cur_region));
return;
}
t_write(&blkhist, (unsigned char *)bs1, 0, 0, ((blk_hdr_ptr_t)lbp)->levl, TRUE, FALSE, GDS_WRITE_KILLTN);
- BUILD_AIMG_IF_JNL_ENABLED(cs_data, cs_addrs->ti->curr_tn);
+ BUILD_AIMG_IF_JNL_ENABLED(cs_data, csa->ti->curr_tn);
t_end(&dummy_hist, NULL, TN_NOT_SPECIFIED);
-
free(lbp);
return;
}
diff --git a/sr_port/dse_adstar.c b/sr_port/dse_adstar.c
index 0c622a2..1d0b0ca 100644
--- a/sr_port/dse_adstar.c
+++ b/sr_port/dse_adstar.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -36,59 +36,49 @@
#include "gvcst_blk_build.h"
#include "util.h"
#include "t_abort.h"
+#include "gtmmsg.h"
GBLREF char *update_array, *update_array_ptr;
-GBLREF gd_region *gv_cur_region;
-GBLREF uint4 update_array_size;
+GBLREF cw_set_element cw_set[];
+GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF sgmnt_data_ptr_t cs_data;
GBLREF srch_hist dummy_hist;
-GBLREF block_id patch_curr_blk;
-GBLREF cw_set_element cw_set[];
+GBLREF uint4 update_array_size;
+error_def(ERR_AIMGBLKFAIL);
error_def(ERR_DBRDONLY);
error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_DSEFAIL);
void dse_adstar(void)
{
- uchar_ptr_t lbp, b_top;
- block_id blk;
blk_segment *bs1, *bs_ptr;
+ block_id blk, blk_ptr;
int4 blk_seg_cnt, blk_size;
short rsize;
- int tmp_cmpc;
srch_blk_status blkhist;
+ uchar_ptr_t b_top, lbp;
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- patch_curr_blk = blk;
- }
- if (patch_curr_blk < 0 || patch_curr_blk >= cs_addrs->ti->total_blks || !(patch_curr_blk % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSENOBML, DSEBLKCUR))) /* WARNING: assignment */
return;
- }
- if (cli_present("POINTER") != CLI_PRESENT)
+ if (CLI_PRESENT != cli_present("POINTER"))
{
util_out_print("Error: block pointer must be specified.", TRUE);
return;
}
- if (!cli_get_hex("POINTER", (uint4 *)&blk))
+ if (BADDSEBLK == (blk_ptr = dse_getblk("POINTER", DSENOBML, DSEBLKNOCUR))) /* WARNING: assignment */
return;
t_begin_crit(ERR_DSEFAIL);
blk_size = cs_addrs->hdr->blk_size;
- blkhist.blk_num = patch_curr_blk;
+ blkhist.blk_num = blk;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
lbp = (uchar_ptr_t)malloc(blk_size);
memcpy(lbp, blkhist.buffaddr, blk_size);
-
if (!((blk_hdr_ptr_t)lbp)->levl)
{
util_out_print("Error: cannot add a star record to a data block.", TRUE);
@@ -112,14 +102,13 @@ void dse_adstar(void)
rsize = SIZEOF(rec_hdr) + SIZEOF(block_id);
PUT_SHORT(&((rec_hdr_ptr_t)b_top)->rsiz, rsize);
SET_CMPC((rec_hdr_ptr_t)b_top, 0);
- PUT_LONG((block_id_ptr_t)(b_top + SIZEOF(rec_hdr)), blk);
+ PUT_LONG((block_id_ptr_t)(b_top + SIZEOF(rec_hdr)), blk_ptr);
((blk_hdr_ptr_t)lbp)->bsiz += (unsigned int)(SIZEOF(rec_hdr) + SIZEOF(block_id));
-
BLK_INIT(bs_ptr, bs1);
BLK_SEG(bs_ptr, (uchar_ptr_t)lbp + SIZEOF(blk_hdr), (int)((blk_hdr_ptr_t)lbp)->bsiz - SIZEOF(blk_hdr));
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, blk, DB_LEN_STR(gv_cur_region));
free(lbp);
t_abort(gv_cur_region, cs_addrs);
return;
@@ -127,7 +116,6 @@ void dse_adstar(void)
t_write(&blkhist, (unsigned char *)bs1, 0, 0, ((blk_hdr_ptr_t)lbp)->levl, TRUE, FALSE, GDS_WRITE_KILLTN);
BUILD_AIMG_IF_JNL_ENABLED(cs_data, cs_addrs->ti->curr_tn);
t_end(&dummy_hist, NULL, TN_NOT_SPECIFIED);
-
free(lbp);
return;
}
diff --git a/sr_port/dse_b_dmp.c b/sr_port/dse_b_dmp.c
index a44d044..4d88083 100644
--- a/sr_port/dse_b_dmp.c
+++ b/sr_port/dse_b_dmp.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -35,13 +35,11 @@
#define CORRUPT_CHAR "?"
#define MAX_UTIL_LEN 80
-GBLREF VSIG_ATOMIC_T util_interrupt;
-GBLREF block_id patch_curr_blk;
-GBLREF sgmnt_addrs *cs_addrs;
GBLREF gd_region *gv_cur_region;
-GBLREF int patch_is_fdmp;
-GBLREF int patch_fdmp_recs;
-GBLREF int patch_rec_counter;
+GBLREF int patch_is_fdmp, patch_rec_counter;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF VSIG_ATOMIC_T util_interrupt;
+
LITREF char *gtm_dbversion_table[];
error_def(ERR_BITMAPSBAD);
@@ -50,27 +48,17 @@ error_def(ERR_DSEBLKRDFAIL);
boolean_t dse_b_dmp(void)
{
- int4 util_len, head, lmap_num, iter1, iter2, mapsize, bplmap, nocrit_present, dummy_int, len, count;
- unsigned char util_buff[MAX_UTIL_LEN], mask;
- boolean_t free, was_crit, was_hold_onto_crit, invalid_bitmap = FALSE, is_mm;
- block_id blk;
- sm_uc_ptr_t bp, b_top, rp, mb, dump_record(sm_uc_ptr_t rp, block_id blk, sm_uc_ptr_t bp, sm_uc_ptr_t b_top);
cache_rec_ptr_t cr;
+ block_id blk;
+ boolean_t free, invalid_bitmap = FALSE, is_mm, was_crit, was_hold_onto_crit;
enum db_ver ondsk_blkver;
+ int4 bplmap, count, dummy_int, head, iter1, iter2, len, lmap_num, mapsize, nocrit_present, util_len;
+ sm_uc_ptr_t bp, b_top, mb, rp;
+ unsigned char mask, util_buff[MAX_UTIL_LEN];
head = cli_present("HEADER");
- if (CLI_PRESENT == cli_present("BLOCK"))
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return FALSE;
- if (blk < 0 || blk >= cs_addrs->ti->total_blks)
- {
- util_out_print("Error: invalid block number.", TRUE);
- return FALSE;
- }
- patch_curr_blk = blk;
- } else
- blk = patch_curr_blk;
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSEBMLOK, DSEBLKCUR))) /* WARNING: assignment */
+ return FALSE;
if (CLI_PRESENT == cli_present("COUNT"))
{
if (!cli_get_hex("COUNT", (uint4 *)&count))
@@ -79,7 +67,6 @@ boolean_t dse_b_dmp(void)
return FALSE;
} else
count = 1;
-
util_out_print(0, TRUE);
bplmap = cs_addrs->hdr->bplmap;
is_mm = (dba_mm == cs_addrs->hdr->acc_meth);
@@ -95,7 +82,7 @@ boolean_t dse_b_dmp(void)
if (!(bp = t_qread(blk, &dummy_int, &cr)))
{
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
}
if (((blk_hdr_ptr_t) bp)->levl && patch_is_fdmp)
{
@@ -139,7 +126,7 @@ boolean_t dse_b_dmp(void)
if (util_interrupt)
{
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- rts_error(VARLSTCNT(1) ERR_CTRLC);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
break;
}
if (CLI_NEGATED == head)
@@ -149,12 +136,11 @@ boolean_t dse_b_dmp(void)
if (!(bp = t_qread(blk, &dummy_int, &cr)))
{
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
}
if (CLI_NEGATED != head)
{
-
- if (bplmap == 0)
+ if (0 == bplmap)
{
memcpy(util_buff, "Block ", 6);
util_len = 6;
@@ -199,7 +185,6 @@ boolean_t dse_b_dmp(void)
if (CLI_PRESENT != head)
{
util_out_print(" !_Low order High order", TRUE);
-
lmap_num = 0;
while (lmap_num < bplmap)
{ memcpy(util_buff, "Block ", 6);
@@ -237,7 +222,7 @@ boolean_t dse_b_dmp(void)
{
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs,
gv_cur_region);
- rts_error(VARLSTCNT(1) ERR_CTRLC);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
}
}
util_out_print("!/'!AD' == BUSY '!AD' == FREE '!AD' == REUSABLE '!AD' == CORRUPT!/",
@@ -246,7 +231,7 @@ boolean_t dse_b_dmp(void)
{
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs,
gv_cur_region);
- rts_error(VARLSTCNT(1) ERR_BITMAPSBAD);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_BITMAPSBAD);
}
}
}
@@ -257,7 +242,6 @@ boolean_t dse_b_dmp(void)
if (blk >= cs_addrs->ti->total_blks)
blk = 0;
}
- patch_curr_blk = blk;
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
return TRUE;
}
diff --git a/sr_port/dse_cache.c b/sr_port/dse_cache.c
index 9d452de..31f326b 100644
--- a/sr_port/dse_cache.c
+++ b/sr_port/dse_cache.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -38,7 +38,7 @@ GBLREF gd_addr *original_header;
error_def(ERR_SIZENOTVALID4);
-#define DB_ABS2REL(X) ((sm_uc_ptr_t)(X) - (sm_uc_ptr_t)csa->nl)
+#define DB_ABS2REL(X) (uintszofptr_t)((uintszofptr_t)(X) - (uintszofptr_t)csa->nl)
#define MAX_UTIL_LEN 40
#define CLEAN_VERIFY "verification is clean"
#define UNCLEAN_VERIFY "verification is NOT clean (see operator log for details)"
@@ -49,18 +49,20 @@ error_def(ERR_SIZENOTVALID4);
void dse_cache(void)
{
- boolean_t all_present, change_present, recover_present, show_present, verify_present, was_crit, is_clean;
- boolean_t nocrit_present, offset_present, size_present, value_present;
- gd_region *reg, *r_top;
- sgmnt_addrs *csa;
- mval dollarh_mval, zdate_mval;
- int4 size;
- uint4 offset, value, old_value, lcnt;
- char dollarh_buffer[MAXNUMLEN], zdate_buffer[SIZEOF(DSE_DMP_TIME_FMT)];
- char temp_str[256], temp_str1[256];
- sm_uc_ptr_t chng_ptr;
- cache_rec_ptr_t cr_que_lo;
- boolean_t is_mm, was_hold_onto_crit, wc_blocked_ok;
+ boolean_t all_present, change_present, recover_present, show_present, verify_present, was_crit, is_clean;
+ boolean_t nocrit_present, offset_present, size_present, value_present;
+ gd_region *reg, *r_top;
+ sgmnt_addrs *csa;
+ sgmnt_data_ptr_t csd;
+ mval dollarh_mval, zdate_mval;
+ int4 size;
+ uint4 offset, value, old_value, lcnt;
+ char dollarh_buffer[MAXNUMLEN], zdate_buffer[SIZEOF(DSE_DMP_TIME_FMT)];
+ char temp_str[256], temp_str1[256];
+ sm_uc_ptr_t chng_ptr;
+ cache_rec_ptr_t cr_que_lo;
+ boolean_t is_mm, was_hold_onto_crit, wc_blocked_ok;
+ uintszofptr_t section_offset;
all_present = (CLI_PRESENT == cli_present("ALL"));
@@ -200,35 +202,47 @@ void dse_cache(void)
TRUE, REG_LEN_STR(reg), DB_ABS2REL(csa->shmpool_buffer));
util_out_print("Region !AD : lock_space = 0x!XJ",
TRUE, REG_LEN_STR(reg), DB_ABS2REL(csa->lock_addrs[0]));
+ csd = csa->hdr;
if (!is_mm)
{
util_out_print("Region !AD : cache_queues_state = 0x!XJ",
TRUE, REG_LEN_STR(reg), DB_ABS2REL(csa->acc_meth.bg.cache_state));
cr_que_lo = &csa->acc_meth.bg.cache_state->cache_array[0];
util_out_print("Region !AD : cache_que_header = 0x!XJ : Numelems = 0x!XL : Elemsize = 0x!XL",
- TRUE, REG_LEN_STR(reg), DB_ABS2REL(cr_que_lo), csa->hdr->bt_buckets, SIZEOF(cache_rec));
+ TRUE, REG_LEN_STR(reg), DB_ABS2REL(cr_que_lo), csd->bt_buckets, SIZEOF(cache_rec));
util_out_print("Region !AD : cache_record = 0x!XJ : Numelems = 0x!XL : Elemsize = 0x!XL",
- TRUE, REG_LEN_STR(reg), DB_ABS2REL(cr_que_lo + csa->hdr->bt_buckets), csa->hdr->n_bts,
+ TRUE, REG_LEN_STR(reg), DB_ABS2REL(cr_que_lo + csd->bt_buckets), csd->n_bts,
SIZEOF(cache_rec));
+ section_offset = ROUND_UP2(DB_ABS2REL(cr_que_lo + csd->bt_buckets + csd->n_bts), OS_PAGE_SIZE);
util_out_print("Region !AD : global_buffer = 0x!XJ : Numelems = 0x!XL : Elemsize = 0x!XL",
- TRUE, REG_LEN_STR(reg),
- ROUND_UP2(DB_ABS2REL(cr_que_lo + csa->hdr->bt_buckets + csa->hdr->n_bts), OS_PAGE_SIZE),
- csa->hdr->n_bts, csa->hdr->blk_size);
+ TRUE, REG_LEN_STR(reg), section_offset, csd->n_bts, csd->blk_size);
+# ifdef GTM_CRYPT
+ if (csd->is_encrypted)
+ {
+ section_offset += (gtm_uint64_t)csd->n_bts * csd->blk_size;
+ /* In case of an encrypted database, bp_top is actually the beginning of the encrypted
+ * global buffer array (an array maintained parallely with the regular unencrypted
+ * global buffer array).
+ */
+ util_out_print("Region !AD : encrypted_globuff = 0x!XJ : Numelems = 0x!XL : Elemsize = "
+ "0x!XL", TRUE, REG_LEN_STR(reg), section_offset, csd->n_bts, csd->blk_size);
+ }
+# endif
util_out_print("Region !AD : db_file_header = 0x!XJ", TRUE,
- REG_LEN_STR(reg), DB_ABS2REL(csa->hdr));
+ REG_LEN_STR(reg), DB_ABS2REL(csd));
util_out_print("Region !AD : bt_que_header = 0x!XJ : Numelems = 0x!XL : Elemsize = 0x!XL",
- TRUE, REG_LEN_STR(reg), DB_ABS2REL(csa->bt_header), csa->hdr->bt_buckets, SIZEOF(bt_rec));
+ TRUE, REG_LEN_STR(reg), DB_ABS2REL(csa->bt_header), csd->bt_buckets, SIZEOF(bt_rec));
util_out_print("Region !AD : th_base = 0x!XJ",
TRUE, REG_LEN_STR(reg), DB_ABS2REL(csa->th_base));
util_out_print("Region !AD : bt_record = 0x!XJ : Numelems = 0x!XL : Elemsize = 0x!XL",
- TRUE, REG_LEN_STR(reg), DB_ABS2REL(csa->bt_base), csa->hdr->n_bts, SIZEOF(bt_rec));
- util_out_print("Region !AD : shared_memory_size = 0x!XL",
+ TRUE, REG_LEN_STR(reg), DB_ABS2REL(csa->bt_base), csd->n_bts, SIZEOF(bt_rec));
+ util_out_print("Region !AD : shared_memory_size = 0x!XJ",
TRUE, REG_LEN_STR(reg), csa->nl->sec_size VMS_ONLY(* OS_PAGELET_SIZE));
} else
{
- util_out_print("Region !AD : shared_memory_size = 0x!XL",
+ util_out_print("Region !AD : shared_memory_size = 0x!XJ",
TRUE, REG_LEN_STR(reg), csa->nl->sec_size VMS_ONLY(* OS_PAGELET_SIZE));
- util_out_print("Region !AD : db_file_header = 0x!XJ", TRUE, REG_LEN_STR(reg), csa->hdr);
+ util_out_print("Region !AD : db_file_header = 0x!XJ", TRUE, REG_LEN_STR(reg), csd);
}
}
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, csa, reg);
diff --git a/sr_port/dse_chng_bhead.c b/sr_port/dse_chng_bhead.c
index 0e725b5..81edd59 100644
--- a/sr_port/dse_chng_bhead.c
+++ b/sr_port/dse_chng_bhead.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,78 +42,57 @@
#include "util.h"
#include "t_abort.h"
#include "gvcst_blk_build.h" /* for the BUILD_AIMG_IF_JNL_ENABLED macro */
+#include "gtmmsg.h"
#ifdef GTM_CRYPT
#include "gtmcrypt.h"
#endif
+GBLREF cache_rec *cr_array[((MAX_BT_DEPTH * 2) - 1) * 2]; /* Maximum number of blocks that can be in transaction */
GBLREF char *update_array, *update_array_ptr;
-GBLREF uint4 update_array_size;
-GBLREF srch_hist dummy_hist;
+GBLREF cw_set_element cw_set[];
+GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF block_id patch_curr_blk;
-GBLREF gd_region *gv_cur_region;
-GBLREF cache_rec *cr_array[((MAX_BT_DEPTH * 2) - 1) * 2]; /* Maximum number of blocks that can be in transaction */
-GBLREF boolean_t unhandled_stale_timer_pop;
-GBLREF cw_set_element cw_set[];
+GBLREF srch_hist dummy_hist;
+GBLREF uint4 update_array_size;
+error_def(ERR_AIMGBLKFAIL);
error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_DSEFAIL);
error_def(ERR_DBRDONLY);
void dse_chng_bhead(void)
{
- block_id blk;
- int4 x;
- trans_num tn;
- cache_rec_ptr_t cr;
blk_hdr new_hdr;
blk_segment *bs1, *bs_ptr;
+ block_id blk;
+ boolean_t chng_blk, ismap, was_hold_onto_crit;
int4 blk_seg_cnt, blk_size; /* needed for BLK_INIT,BLK_SEG and BLK_FINI macros */
- boolean_t ismap;
- boolean_t chng_blk;
- boolean_t was_crit;
- boolean_t was_hold_onto_crit;
- uint4 mapsize;
- srch_blk_status blkhist;
+ int4 x;
sgmnt_addrs *csa;
sgmnt_data_ptr_t csd;
-# ifdef GTM_CRYPT
- int req_enc_blk_size;
- int gtmcrypt_errno;
- blk_hdr_ptr_t bp, save_bp, save_old_block;
- gd_segment *seg;
-# endif
+ srch_blk_status blkhist;
+ trans_num tn;
+ uint4 mapsize;
csa = cs_addrs;
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
chng_blk = FALSE;
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- if (blk < 0 || blk > csa->ti->total_blks)
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
- patch_curr_blk = blk;
- }
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSEBMLOK, DSEBLKCUR))) /* WARNING: assignment */
+ return;
csd = csa->hdr;
assert(csd == cs_data);
blk_size = csd->blk_size;
- ismap = (patch_curr_blk / csd->bplmap * csd->bplmap == patch_curr_blk);
+ ismap = IS_BITMAP_BLK(blk);
mapsize = BM_SIZE(csd->bplmap);
-
t_begin_crit(ERR_DSEFAIL);
- blkhist.blk_num = patch_curr_blk;
+ blkhist.blk_num = blk;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
rts_error_csa(CSA_ARG(csa) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
new_hdr = *(blk_hdr_ptr_t)blkhist.buffaddr;
-
- if (cli_present("LEVEL") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("LEVEL"))
{
if (!cli_get_hex("LEVEL", (uint4 *)&x))
{
@@ -132,15 +111,14 @@ void dse_chng_bhead(void)
t_abort(gv_cur_region, csa);
return;
}
- new_hdr.levl = (unsigned char)x;
-
+ new_hdr.levl = (unsigned char)x;
chng_blk = TRUE;
if (new_hdr.bsiz < SIZEOF(blk_hdr))
new_hdr.bsiz = SIZEOF(blk_hdr);
if (new_hdr.bsiz > blk_size)
new_hdr.bsiz = blk_size;
}
- if (cli_present("BSIZ") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("BSIZ"))
{
if (!cli_get_hex("BSIZ", (uint4 *)&x))
{
@@ -169,7 +147,7 @@ void dse_chng_bhead(void)
BLK_SEG(bs_ptr, blkhist.buffaddr + SIZEOF(new_hdr), new_hdr.bsiz - SIZEOF(new_hdr));
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad block build.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, blk, DB_LEN_STR(gv_cur_region));
t_abort(gv_cur_region, csa);
return;
}
@@ -177,17 +155,16 @@ void dse_chng_bhead(void)
BUILD_AIMG_IF_JNL_ENABLED(csd, csa->ti->curr_tn);
t_end(&dummy_hist, NULL, TN_NOT_SPECIFIED);
}
- if (cli_present("TN") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("TN"))
{
if (!cli_get_hex64("TN", &tn))
return;
- was_crit = csa->now_crit;
t_begin_crit(ERR_DSEFAIL);
CHECK_TN(csa, csd, csd->trans_hist.curr_tn); /* can issue rts_error TNTOOLARGE */
assert(csa->ti->early_tn == csa->ti->curr_tn);
if (NULL == (blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
{
- util_out_print("Error: Unable to read buffer.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
t_abort(gv_cur_region, csa);
return;
}
@@ -201,60 +178,7 @@ void dse_chng_bhead(void)
t_write(&blkhist, (unsigned char *)bs1, 0, 0,
((blk_hdr_ptr_t)blkhist.buffaddr)->levl, TRUE, FALSE, GDS_WRITE_KILLTN);
/* Pass the desired tn as argument to bg_update/mm_update below */
- BUILD_AIMG_IF_JNL_ENABLED(csd, tn);
- was_hold_onto_crit = csa->hold_onto_crit;
- csa->hold_onto_crit = TRUE; /* need this so t_end doesn't release crit (see below comment for why) */
- t_end(&dummy_hist, NULL, tn);
-# ifdef GTM_CRYPT
- if (csd->is_encrypted && (tn < csa->ti->curr_tn))
- { /* BG and db encryption is enabled and the DSE update caused the block-header to potentially have a tn
- * that is LESS than what it had before. At this point, the global buffer (corresponding to blkhist.blk_num)
- * reflects the contents of the block AFTER the dse update (bg_update would have touched this) whereas
- * the corresponding encryption global buffer reflects the contents of the block BEFORE the update.
- * Normally wcs_wtstart takes care of propagating the tn update from the regular global buffer to the
- * corresponding encryption buffer. But if before it gets a chance, let us say a process goes to t_end
- * as part of a subsequent transaction and updates this same block. Since the blk-hdr-tn potentially
- * decreased, it is possible that the PBLK writing check (comparing blk-hdr-tn with the epoch_tn) decides
- * to write a PBLK for this block (even though a PBLK was already written for this block as part of a
- * previous DSE CHANGE -BL -TN in the same epoch). In this case, since the db is encrypted, the logic
- * will assume there were no updates to this block since the last time wcs_wtstart updated the encryption
- * buffer and therefore use that to write the pblk, which is incorrect since it does not yet contain the
- * tn update. The consequence of this is would be writing an older before-image PBLK) record to the
- * journal file. To prevent this situation, we update the encryption buffer here (before releasing crit)
- * using logic like that in wcs_wtstart to ensure it is in sync with the regular global buffer. To ensure
- * that t_end doesn't release crit, we set csa->hold_onto_crit to TRUE
- * Note:
- * Although we use cw_set[0] to access the global buffer corresponding to the block number being updated,
- * cw_set_depth at this point is 0 because t_end resets it. This is considered safe since cw_set is a
- * static array (as opposed to malloc'ed memory) and hence is always available and valid until it gets
- * overwritten by subsequent updates.
- */
- bp = (blk_hdr_ptr_t)GDS_ANY_REL2ABS(csa, cw_set[0].cr->buffaddr);
- DBG_ENSURE_PTR_IS_VALID_GLOBUFF(csa, csd, (sm_uc_ptr_t)bp);
- save_bp = (blk_hdr_ptr_t)GDS_ANY_ENCRYPTGLOBUF(bp, csa);
- DBG_ENSURE_PTR_IS_VALID_ENCTWINGLOBUFF(csa, csd, (sm_uc_ptr_t)save_bp);
- assert((bp->bsiz <= csd->blk_size) && (bp->bsiz >= SIZEOF(*bp)));
- req_enc_blk_size = MIN(csd->blk_size, bp->bsiz) - SIZEOF(*bp);
- if (BLK_NEEDS_ENCRYPTION(bp->levl, req_enc_blk_size))
- {
- ASSERT_ENCRYPTION_INITIALIZED;
- memcpy(save_bp, bp, SIZEOF(blk_hdr));
- GTMCRYPT_ENCRYPT(csa, csa->encr_key_handle, (char *)(bp + 1), req_enc_blk_size,
- (char *)(save_bp + 1), gtmcrypt_errno);
- if (0 != gtmcrypt_errno)
- {
- seg = gv_cur_region->dyn.addr;
- GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, gtm_putmsg, seg->fname_len, seg->fname);
- }
- } else
- memcpy(save_bp, bp, bp->bsiz);
- }
-# endif
- csa->hold_onto_crit = was_hold_onto_crit;
- if (!was_crit)
- rel_crit(gv_cur_region);
- if (unhandled_stale_timer_pop)
- process_deferred_stale();
+ BUILD_AIMG_IF_JNL_ENABLED_AND_T_END_WITH_EFFECTIVE_TN(csa, csd, tn, &dummy_hist);
}
return;
}
diff --git a/sr_port/dse_chng_fhead.c b/sr_port/dse_chng_fhead.c
index 595a54f..1eaf09d 100644
--- a/sr_port/dse_chng_fhead.c
+++ b/sr_port/dse_chng_fhead.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -88,18 +88,13 @@ void dse_chng_fhead(void)
SETUP_THREADGBL_ACCESS;
if (gv_cur_region->read_only)
- rts_error(VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
memset(temp_str, 0, 256);
memset(temp_str1, 0, 256);
memset(buf, 0, MAX_LINE);
was_crit = cs_addrs->now_crit;
- /* If the user requested DSE CHANGE -FILE -CORRUPT, then skip the check in grab_crit, which triggers an rts_error, as this
- * is one of the ways of turning off the file_corrupt flag in the file header
- */
- TREF(skip_file_corrupt_check) = corrupt_file_present = (CLI_PRESENT == cli_present("CORRUPT_FILE"));
nocrit_present = (CLI_NEGATED == cli_present("CRIT"));
DSE_GRAB_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- TREF(skip_file_corrupt_check) = FALSE; /* Now that grab_crit is done, reset the global variable */
if (CLI_PRESENT == cli_present("OVERRIDE"))
override = TRUE;
# ifdef VMS
@@ -114,7 +109,7 @@ void dse_chng_fhead(void)
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
util_out_print("Region: !AD is frozen by another user, not releasing freeze.",
TRUE, REG_LEN_STR(gv_cur_region));
- rts_error(VARLSTCNT(4) ERR_FREEZE, 2, REG_LEN_STR(gv_cur_region));
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_FREEZE, 2, REG_LEN_STR(gv_cur_region));
return;
}
@@ -193,7 +188,7 @@ void dse_chng_fhead(void)
(SIZEOF(gtm_int64_t) == size)))
{
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- rts_error(VARLSTCNT(1) ERR_SIZENOTVALID8);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_SIZENOTVALID8);
}
if ((0 > (int4)size) || ((uint4)SGMNT_HDR_LEN < (uint4)location)
|| ((uint4)SGMNT_HDR_LEN < ((uint4)location + (uint4)size)))
@@ -257,7 +252,7 @@ void dse_chng_fhead(void)
else
{
cs_data->blk_size = ((x/DISK_BLOCK_SIZE) + 1) * DISK_BLOCK_SIZE;
- gtm_putmsg(VARLSTCNT(4) ERR_BLKSIZ512, 2, x, cs_data->blk_size);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BLKSIZ512, 2, x, cs_data->blk_size);
}
}
if ((CLI_PRESENT == cli_present("RECORD_MAX_SIZE")) && (cli_get_int("RECORD_MAX_SIZE", &x)))
@@ -440,6 +435,7 @@ void dse_chng_fhead(void)
if ( -1 != (x = cli_t_f_n("STDNULLCOLL")))
gv_cur_region->std_null_coll = cs_data->std_null_coll = x;
}
+ corrupt_file_present = (CLI_PRESENT == cli_present("CORRUPT_FILE"));
if (corrupt_file_present)
{
x = cli_t_f_n("CORRUPT_FILE");
@@ -551,7 +547,7 @@ void dse_chng_fhead(void)
hiber_start(1000);
if (util_interrupt)
{
- gtm_putmsg(VARLSTCNT(1) ERR_FREEZECTRL);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_FREEZECTRL);
break;
}
}
diff --git a/sr_port/dse_chng_rhead.c b/sr_port/dse_chng_rhead.c
index a911029..1991ffd 100644
--- a/sr_port/dse_chng_rhead.c
+++ b/sr_port/dse_chng_rhead.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -36,50 +36,40 @@
#include "gvcst_blk_build.h"
#include "util.h"
#include "t_abort.h"
+#include "gtmmsg.h"
GBLREF char *update_array, *update_array_ptr;
-GBLREF gd_region *gv_cur_region;
-GBLREF uint4 update_array_size;
+GBLREF cw_set_element cw_set[];
+GBLREF gd_region *gv_cur_region;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF sgmnt_data_ptr_t cs_data;
GBLREF srch_hist dummy_hist;
-GBLREF block_id patch_curr_blk;
GBLREF unsigned short patch_comp_count;
-GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF cw_set_element cw_set[];
+GBLREF uint4 update_array_size;
+error_def(ERR_AIMGBLKFAIL);
error_def(ERR_DBRDONLY);
error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_DSEFAIL);
void dse_chng_rhead(void)
{
+ blk_segment *bs1, *bs_ptr;
block_id blk;
- sm_uc_ptr_t bp, b_top, cp, rp;
boolean_t chng_rec;
- rec_hdr new_rec;
- uint4 x;
- blk_segment *bs1, *bs_ptr;
int4 blk_seg_cnt, blk_size;
- int tmp_cmpc;
+ rec_hdr new_rec;
+ sm_uc_ptr_t bp, b_top, cp, rp;
srch_blk_status blkhist;
+ uint4 x;
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- if(!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- patch_curr_blk = blk;
- }
- if (patch_curr_blk < 0 || patch_curr_blk >= cs_addrs->ti->total_blks || !(patch_curr_blk % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSENOBML, DSEBLKCUR))) /* WARNING: assignment */
return;
- }
-
t_begin_crit(ERR_DSEFAIL);
- blkhist.blk_num = patch_curr_blk;
+ blkhist.blk_num = blk;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
bp = blkhist.buffaddr;
@@ -88,7 +78,7 @@ void dse_chng_rhead(void)
b_top = bp + ((blk_hdr_ptr_t)bp)->bsiz;
if (((blk_hdr_ptr_t)bp)->bsiz > blk_size || ((blk_hdr_ptr_t)bp)->bsiz < SIZEOF(blk_hdr))
chng_rec = TRUE; /* force rewrite to correct size */
- if (cli_present("RECORD") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("RECORD"))
{
if (!(rp = skan_rnum(bp, FALSE)))
{
@@ -102,7 +92,7 @@ void dse_chng_rhead(void)
}
GET_SHORT(new_rec.rsiz, &((rec_hdr_ptr_t)rp)->rsiz);
SET_CMPC(&new_rec, EVAL_CMPC((rec_hdr_ptr_t)rp));
- if (cli_present("CMPC") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("CMPC"))
{
if (!cli_get_hex("CMPC", &x))
{
@@ -120,7 +110,7 @@ void dse_chng_rhead(void)
SET_CMPC(&new_rec, x);
chng_rec = TRUE;
}
- if (cli_present("RSIZ") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("RSIZ"))
{
if (!cli_get_hex("RSIZ", &x))
{
@@ -151,7 +141,7 @@ void dse_chng_rhead(void)
BLK_SEG(bs_ptr, cp, b_top - cp);
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, blk, DB_LEN_STR(gv_cur_region));
t_abort(gv_cur_region, cs_addrs);
return;
}
diff --git a/sr_port/dse_exhaus.c b/sr_port/dse_exhaus.c
index 0b216ac..7622ab5 100644
--- a/sr_port/dse_exhaus.c
+++ b/sr_port/dse_exhaus.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -31,15 +31,13 @@
#define MAX_UTIL_LEN 32
-GBLDEF short int patch_path_count;
GBLREF block_id patch_find_blk, patch_left_sib, patch_path[MAX_BT_DEPTH + 1], patch_right_sib;
-GBLREF bool patch_exh_found;
-GBLREF bool patch_find_sibs;
-GBLREF bool patch_find_root_search;
+GBLREF boolean_t patch_exh_found, patch_find_root_search, patch_find_sibs;
GBLREF global_root_list *global_roots_head;
GBLREF int4 patch_offset[MAX_BT_DEPTH + 1];
GBLREF sgmnt_addrs *cs_addrs;
+GBLREF short int patch_path_count;
GBLREF VSIG_ATOMIC_T util_interrupt;
error_def(ERR_DSEBLKRDFAIL);
@@ -54,12 +52,12 @@ void dse_exhaus(int4 pp, int4 op)
int4 dummy_int;
global_dir_path *d_ptr, *temp;
short temp_short;
- sm_uc_ptr_t bp, b_top, np, nrp, nr_top, ptr, rp, r_top;
+ sm_uc_ptr_t bp, b_top, nrp, nr_top, ptr, rp, r_top;
last = 0;
patch_path_count++;
- if(!(bp = t_qread(patch_path[pp - 1], &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ if (!(bp = t_qread(patch_path[pp - 1], &dummy_int, &dummy_cr)))
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
if (((blk_hdr_ptr_t) bp)->bsiz > cs_addrs->hdr->blk_size)
b_top = bp + cs_addrs->hdr->blk_size;
else if (SIZEOF(blk_hdr) > ((blk_hdr_ptr_t) bp)->bsiz)
@@ -70,18 +68,9 @@ void dse_exhaus(int4 pp, int4 op)
{
if (util_interrupt)
{
- rts_error(VARLSTCNT(1) ERR_CTRLC);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
break;
}
- if (!(np = t_qread(patch_path[pp - 1], &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
- if (np != bp)
- {
- b_top = np + (b_top - bp);
- rp = np + (rp - bp);
- r_top = np + (r_top - bp);
- bp = np;
- }
GET_SHORT(temp_short, &((rec_hdr_ptr_t)rp)->rsiz);
r_top = rp + temp_short;
if (r_top > b_top)
diff --git a/sr_port/dse_f_blk.c b/sr_port/dse_f_blk.c
index 3c9c9fd..958be72 100644
--- a/sr_port/dse_f_blk.c
+++ b/sr_port/dse_f_blk.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -31,93 +31,86 @@
/* Include prototypes*/
#include "t_qread.h"
-GBLDEF bool patch_exh_found, patch_find_root_search, patch_find_sibs;
+GBLDEF boolean_t patch_exh_found, patch_find_root_search, patch_find_sibs;
GBLDEF block_id patch_find_blk, patch_left_sib, patch_right_sib;
GBLDEF block_id patch_path[MAX_BT_DEPTH + 1], patch_path1[MAX_BT_DEPTH + 1];
GBLDEF global_root_list *global_roots_head, *global_roots_tail;
GBLDEF int4 patch_offset[MAX_BT_DEPTH + 1], patch_offset1[MAX_BT_DEPTH + 1];
-GBLDEF short int patch_dir_path_count;
+GBLDEF short int patch_dir_path_count, patch_path_count;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF gd_region *gv_cur_region;
-GBLREF block_id patch_curr_blk;
-GBLREF short int patch_path_count;
#define MAX_UTIL_LEN 33
static boolean_t was_crit, was_hold_onto_crit, nocrit_present;
-error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_CTRLC);
+error_def(ERR_DSEBLKRDFAIL);
void dse_f_blk(void)
{
- block_id blk, last, look;
+ block_id last, look;
boolean_t exhaust;
cache_rec_ptr_t dummy_cr;
char targ_key[MAX_KEY_SZ + 1], util_buff[MAX_UTIL_LEN];
- global_root_list *temp;
global_dir_path *d_ptr, *dtemp;
- int util_len;
+ global_root_list *temp;
+ int util_len, lvl, parent_lvl;
int4 dummy_int;
sm_uc_ptr_t blk_id, bp, b_top, key_top, rp, r_top, sp, srp, s_top;
short int count, rsize, size;
- char lvl;
- if (CLI_PRESENT == cli_present("BLOCK"))
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- if ((0 > blk) || (blk >= cs_addrs->ti->total_blks) || !(blk % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
- patch_curr_blk = blk;
- }
+ if (BADDSEBLK == (patch_find_blk = dse_getblk("BLOCK", DSENOBML, DSEBLKCUR))) /* WARNING: assignment */
+ return;
patch_find_sibs = (CLI_PRESENT == cli_present("SIBLINGS"));
- patch_find_blk = patch_curr_blk;
was_crit = cs_addrs->now_crit;
nocrit_present = (CLI_NEGATED == cli_present("CRIT"));
DSE_GRAB_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
/* ESTABLISH is done here because dse_f_blk_ch() assumes we already have crit. */
ESTABLISH(dse_f_blk_ch);
- if (!(bp = t_qread(patch_find_blk, &dummy_int, &dummy_cr)))
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
- if (((blk_hdr_ptr_t) bp)->bsiz > cs_addrs->hdr->blk_size)
- b_top = bp + cs_addrs->hdr->blk_size;
- else if (SIZEOF(blk_hdr) > ((blk_hdr_ptr_t) bp)->bsiz)
- b_top = bp + SIZEOF(blk_hdr);
- else
- b_top = bp + ((blk_hdr_ptr_t)bp)->bsiz;
- rp = bp + SIZEOF(blk_hdr);
- GET_SHORT(rsize, &((rec_hdr_ptr_t) rp)->rsiz);
- if (SIZEOF(rec_hdr) > rsize)
- r_top = rp + SIZEOF(rec_hdr);
- else
- r_top = rp + rsize;
- if (r_top > b_top)
- r_top = b_top;
- for (key_top = rp + SIZEOF(rec_hdr); (key_top < r_top) && *key_top++; )
- ;
- if (((blk_hdr_ptr_t)bp)->levl && key_top > (blk_id = r_top - SIZEOF(block_id))) /* NOTE assignment */
- key_top = blk_id;
+ look = patch_find_blk;
+ parent_lvl = 0;
+ do
+ {
+ if (!(bp = t_qread(look, &dummy_int, &dummy_cr)))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ if (((blk_hdr_ptr_t) bp)->bsiz > cs_addrs->hdr->blk_size)
+ b_top = bp + cs_addrs->hdr->blk_size;
+ else if (SIZEOF(blk_hdr) > ((blk_hdr_ptr_t) bp)->bsiz)
+ b_top = bp + SIZEOF(blk_hdr);
+ else
+ b_top = bp + ((blk_hdr_ptr_t)bp)->bsiz;
+ rp = bp + SIZEOF(blk_hdr);
+ GET_SHORT(rsize, &((rec_hdr_ptr_t) rp)->rsiz);
+ if (SIZEOF(rec_hdr) > rsize)
+ r_top = rp + SIZEOF(rec_hdr);
+ else
+ r_top = rp + rsize;
+ if (r_top > b_top)
+ r_top = b_top;
+ for (key_top = rp + SIZEOF(rec_hdr); (key_top < r_top) && *key_top++; )
+ ;
+ lvl = ((blk_hdr_ptr_t)bp)->levl;
+ if (lvl && key_top > (blk_id = r_top - SIZEOF(block_id))) /* NOTE assignment */
+ key_top = blk_id;
+ size = key_top - rp - SIZEOF(rec_hdr);
+ if (SIZEOF(targ_key) < size)
+ size = SIZEOF(targ_key);
+ if (!lvl || size)
+ break; /* data block OR index block with a non-* key found. break right away to do search */
+ if ((0 > lvl) || (lvl >= MAX_BT_DEPTH) || (parent_lvl && (parent_lvl != (lvl + 1))))
+ break; /* out-of-design level (integ error in db). do not descend anymore. do exhaustive search */
+ parent_lvl = lvl;
+ /* while it is an index block with only a *-record keep looking in child blocks for key */
+ GET_ULONG(look, blk_id);
+ } while (TRUE);
patch_path_count = 1;
patch_path[0] = get_dir_root();
patch_left_sib = patch_right_sib = 0;
- size = key_top - rp - SIZEOF(rec_hdr);
- if (SIZEOF(targ_key) < size)
- size = SIZEOF(targ_key);
patch_find_root_search = TRUE;
- if ((exhaust = (cli_present("EXHAUSTIVE") == CLI_PRESENT)) || (0 >= size)) /* NOTE assignment */
+ if ((exhaust = (CLI_PRESENT == cli_present("EXHAUSTIVE"))) || (0 >= size)) /* NOTE assignment */
{
- if (size < 0)
- {
- util_out_print("No keys in block, cannot perform ordered search.", TRUE);
- DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- REVERT;
- return;
- }
if (patch_exh_found = (patch_find_blk == patch_path[0])) /* NOTE assignment */
{
if (patch_find_sibs)
@@ -483,7 +476,7 @@ void dse_f_blk(void)
/* Control-C condition handler */
CONDITION_HANDLER(dse_f_blk_ch)
{
- START_CH(SIGNAL != ERR_CTRLC);
+ START_CH(TRUE);
if (ERR_CTRLC == SIGNAL)
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
diff --git a/sr_port/dse_f_free.c b/sr_port/dse_f_free.c
index c7de01a..80ece38 100644
--- a/sr_port/dse_f_free.c
+++ b/sr_port/dse_f_free.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -28,8 +28,8 @@
/* Include prototypes */
#include "t_qread.h"
-GBLREF sgmnt_addrs *cs_addrs;
GBLREF gd_region *gv_cur_region;
+GBLREF sgmnt_addrs *cs_addrs;
error_def(ERR_DSEBLKRDFAIL);
@@ -38,31 +38,24 @@ error_def(ERR_DSEBLKRDFAIL);
void dse_f_free(void)
{
block_id blk;
- bool in_last_bmap;
+ boolean_t in_last_bmap, was_crit, was_hold_onto_crit;
+ cache_rec_ptr_t dummy_cr;
char util_buff[MAX_UTIL_LEN];
+ int4 bplmap, dummy_int, hint_mod_bplmap, hint_over_bplmap;
+ int4 lmap_bit, master_bit, nocrit_present, total_blks, util_len;
sm_uc_ptr_t lmap_base;
- int4 bplmap, total_blks;
- int4 util_len, master_bit, lmap_bit, hint_over_bplmap, hint_mod_bplmap;
- boolean_t was_crit, was_hold_onto_crit;
- int4 dummy_int, nocrit_present;
- cache_rec_ptr_t dummy_cr;
- if (cs_addrs->hdr->bplmap == 0)
+ if (0 == cs_addrs->hdr->bplmap)
{ util_out_print("Cannot perform free block search: bplmap field of file header is zero.", TRUE);
return;
}
bplmap = cs_addrs->hdr->bplmap;
-
- if(!cli_get_hex("HINT", (uint4 *)&blk))
- return;
- if (blk < 0 || blk >= cs_addrs->ti->total_blks || (blk / bplmap * bplmap == blk))
- { util_out_print("Error: invalid block number.", TRUE);
+ if (BADDSEBLK == (blk = dse_getblk("HINT", DSEBMLOK, DSEBLKNOCUR))) /* WARNING: assignment */
return;
- }
hint_over_bplmap = blk / bplmap;
master_bit = bmm_find_free(hint_over_bplmap, cs_addrs->bmm,
(cs_addrs->ti->total_blks + bplmap - 1)/ bplmap);
- if (master_bit == -1)
+ if (-1 == master_bit)
{ util_out_print("Error: database full.", TRUE);
return;
}
@@ -71,7 +64,7 @@ void dse_f_free(void)
nocrit_present = (CLI_NEGATED == cli_present("CRIT"));
DSE_GRAB_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
if(!(lmap_base = t_qread(master_bit * bplmap, &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
if (master_bit == hint_over_bplmap)
hint_mod_bplmap = blk - blk / bplmap * bplmap;
else
@@ -81,7 +74,7 @@ void dse_f_free(void)
else
total_blks = bplmap;
lmap_bit = bml_find_free(hint_mod_bplmap, lmap_base + SIZEOF(blk_hdr), total_blks);
- if (lmap_bit == -1)
+ if (-1 == lmap_bit)
{ memcpy(util_buff, "Error: bit map in block ", 24);
util_len = 24;
util_len += i2hex_nofill(master_bit * bplmap, (uchar_ptr_t)&util_buff[util_len], 8);
diff --git a/sr_port/dse_f_reg.c b/sr_port/dse_f_reg.c
index 554a891..3e5803c 100644
--- a/sr_port/dse_f_reg.c
+++ b/sr_port/dse_f_reg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,6 +22,7 @@
#include "util.h"
#include "cli.h"
#include "dse.h"
+#include "gtmmsg.h"
GBLREF block_id patch_curr_blk;
GBLREF gd_region *gv_cur_region;
@@ -33,6 +34,11 @@ GBLREF gd_addr *original_header;
GBLREF gv_namehead *gv_target;
GBLREF gv_key *gv_currkey;
+error_def(ERR_DSENOTOPEN);
+error_def(ERR_NOGTCMDB);
+error_def(ERR_NOREGION);
+error_def(ERR_NOUSERDB);
+
void dse_f_reg(void)
{
char rn[MAX_RN_LEN];
@@ -55,6 +61,8 @@ void dse_f_reg(void)
return;
}
assert(rn[0]);
+ for (i = 0; i < rnlen; i++) /* Region names are always upper-case ASCII */
+ rn[i] = TOUPPER(rn[i]);
found = FALSE;
for (i = 0, ptr = original_header->regions; i < original_header->n_regions ;i++, ptr++)
{
@@ -63,7 +71,7 @@ void dse_f_reg(void)
}
if (!found)
{
- util_out_print("Error: region not found.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOREGION, 2, rnlen, rn);
return;
}
if (ptr == gv_cur_region)
@@ -71,26 +79,29 @@ void dse_f_reg(void)
util_out_print("Error: already in region: !AD", TRUE, REG_LEN_STR(gv_cur_region));
return;
}
- if (dba_cm == REG_ACC_METH(ptr))
+ /* reg_cmcheck would have already been called for ALL regions at region_init time. In Unix, this would have set
+ * reg->dyn.addr->acc_meth to dba_cm if it is remote database. So we can safely use this to check if the region
+ * is dba_cm or not. In VMS though reg_cmcheck does not modify acc_meth so we call reg_cmcheck in that case.
+ */
+ if (UNIX_ONLY(dba_cm == ptr->dyn.addr->acc_meth) VMS_ONLY(reg_cmcheck(ptr)))
{
- util_out_print("Error: Cannot edit an GT.CM database file.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_NOGTCMDB, 4, LEN_AND_LIT("DSE"), rnlen, rn); /* no VMS test */
return;
}
+# ifdef VMS
if (dba_usr == REG_ACC_METH(ptr))
- {
- util_out_print("Error: Cannot edit a non-GDS format database file.", TRUE);
+ { /* VMS only; no test */
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_NOUSERDB, 4, LEN_AND_LIT("DSE"), rnlen, rn);
return;
}
+# endif
if (!ptr->open)
{
- util_out_print("Error: that region was not opened because it is not bound to any namespace.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DSENOTOPEN, 2, rnlen, rn);
return;
}
if (cs_addrs->now_crit)
- {
- util_out_print("Warning: now leaving region in critical section: !AD", TRUE, gv_cur_region->rname_len,
- gv_cur_region->rname);
- }
+ util_out_print("Warning: now leaving region in critical section: !AD", TRUE, REG_LEN_STR(gv_cur_region));
gv_cur_region = ptr;
gv_target = NULL; /* to prevent out-of-sync situations between gv_target and cs_addrs */
assert((dba_mm == REG_ACC_METH(gv_cur_region)) || (dba_bg == REG_ACC_METH(gv_cur_region)));
diff --git a/sr_port/dse_fdmp.c b/sr_port/dse_fdmp.c
index f1ee782..5c7b3e5 100644
--- a/sr_port/dse_fdmp.c
+++ b/sr_port/dse_fdmp.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -55,10 +55,11 @@ boolean_t dse_fdmp(sm_uc_ptr_t data, int len)
unsigned char *key_char_ptr, *work_char_ptr;
int dest_len;
unsigned char *ret_addr;
- boolean_t is_snblk=FALSE;
+ boolean_t is_snblk = FALSE;
span_subs *ss_ptr; /*spanning node key pointer */
unsigned int snbid, offset, trail_zero, rev_num, num;
unsigned short blk_sz;
+ mstr opstr;
if (work_buff_length < ZWR_EXP_RATIO(gv_cur_region->max_rec_size))
{
@@ -77,68 +78,73 @@ boolean_t dse_fdmp(sm_uc_ptr_t data, int len)
return FALSE;
}
key_char_ptr++;
- if (SPAN_START_BYTE != *key_char_ptr) /*Global has subscript*/
+ if (*key_char_ptr)
{
- *work_char_ptr++ = '(';
- for (;;)
+ if (SPAN_START_BYTE != *key_char_ptr) /*Global has subscript*/
{
- work_char_ptr = gvsub2str(key_char_ptr, work_char_ptr, TRUE);
- /* Removed unnecessary checks for printable characters (PRINTABLE()) here
- * since the data being written into files (OPENed files) would have been
- * passed through ZWR translation which would have taken care of converting
- * to $CHAR() or $ZCHAR() */
-
- for (; *key_char_ptr ; key_char_ptr++)
- ;
- key_char_ptr++;
- /* Check if this is spanning node if yes break out of the loop */
- if (SPAN_START_BYTE == *key_char_ptr
- && (int)*(key_char_ptr + 1) >= SPAN_BYTE_MIN
- && (int)*(key_char_ptr + 2) >= SPAN_BYTE_MIN)
+ *work_char_ptr++ = '(';
+ for (;;)
{
- is_snblk = TRUE;
- break;
+ opstr.addr = (char *)work_char_ptr;
+ opstr.len = work_buff_length;
+ work_char_ptr = gvsub2str(key_char_ptr, &opstr, TRUE);
+ /* Removed unnecessary checks for printable characters (PRINTABLE()) here
+ * since the data being written into files (OPENed files) would have been
+ * passed through ZWR translation which would have taken care of converting
+ * to $CHAR() or $ZCHAR() */
+
+ for (; *key_char_ptr ; key_char_ptr++)
+ ;
+ key_char_ptr++;
+ /* Check if this is spanning node if yes break out of the loop */
+ if (SPAN_START_BYTE == *key_char_ptr
+ && (int)*(key_char_ptr + 1) >= SPAN_BYTE_MIN
+ && (int)*(key_char_ptr + 2) >= SPAN_BYTE_MIN)
+ {
+ is_snblk = TRUE;
+ break;
+ }
+ if (*key_char_ptr)
+ *work_char_ptr++ = ',';
+ else
+ break;
}
- if (*key_char_ptr)
- *work_char_ptr++ = ',';
- else
- break;
- }
- *work_char_ptr++ = ')';
- } else /*Spanning node without subscript*/
- is_snblk = TRUE;
- if (is_snblk)
- {
- ss_ptr = (span_subs *)key_char_ptr;
- snbid = SPAN_GVSUBS2INT(ss_ptr);
- key_char_ptr = key_char_ptr + SPAN_SUBS_LEN + 1; /* Move out of special subscript of spanning node */
- blk_sz = gv_cur_region->dyn.addr->blk_size;
- /* Decide the offset of the content of a block inside the value of spanning node*/
- offset = (snbid) ? (blk_sz - (SIZEOF(blk_hdr) + SIZEOF(rec_hdr) + gv_cur_region->dyn.addr->reserved_bytes
- + (key_char_ptr - (uchar_ptr_t)patch_comp_key + 1))) * (snbid - 1) : 0 ;
- ret_addr =(unsigned char *)memmove((void *)(work_buff+4), (void *)work_buff, (work_char_ptr - work_buff));
- assert(*ret_addr == '^');
- *work_buff = '$';
- *(work_buff + 1) = 'z';
- *(work_buff + 2) = 'e';
- *(work_buff + 3) = '(';
- /* length of "$ze(" is 4, so move the work_char_ptr by 4*/
- work_char_ptr = work_char_ptr + 4;
- *work_char_ptr++ = ',';
+ *work_char_ptr++ = ')';
+ } else /*Spanning node without subscript*/
+ is_snblk = TRUE;
+ if (is_snblk)
+ {
+ ss_ptr = (span_subs *)key_char_ptr;
+ snbid = SPAN_GVSUBS2INT(ss_ptr);
+ key_char_ptr = key_char_ptr + SPAN_SUBS_LEN + 1; /* Move out of special subscript of spanning node */
+ blk_sz = gv_cur_region->dyn.addr->blk_size;
+ /* Decide the offset of the content of a block inside the value of spanning node*/
+ offset = (snbid) ? (blk_sz - (SIZEOF(blk_hdr) + SIZEOF(rec_hdr) + gv_cur_region->dyn.addr->reserved_bytes
+ + (key_char_ptr - (uchar_ptr_t)patch_comp_key + 1))) * (snbid - 1) : 0 ;
+ ret_addr =(unsigned char *)memmove((void *)(work_buff+4), (void *)work_buff, (work_char_ptr - work_buff));
+ assert(*ret_addr == '^');
+ *work_buff = '$';
+ *(work_buff + 1) = 'z';
+ *(work_buff + 2) = 'e';
+ *(work_buff + 3) = '(';
+ /* length of "$ze(" is 4, so move the work_char_ptr by 4*/
+ work_char_ptr = work_char_ptr + 4;
+ *work_char_ptr++ = ',';
- /* Dump the offset of the content of a block inside the value of spanning node */
- num = snbid ? offset : 0;
- COUNT_TRAILING_ZERO(num, work_char_ptr, trail_zero);
- num = offset;
- OUTPUT_NUMBER(num, work_char_ptr, trail_zero);
- *work_char_ptr++ = ',';
+ /* Dump the offset of the content of a block inside the value of spanning node */
+ num = snbid ? offset : 0;
+ COUNT_TRAILING_ZERO(num, work_char_ptr, trail_zero);
+ num = offset;
+ OUTPUT_NUMBER(num, work_char_ptr, trail_zero);
+ *work_char_ptr++ = ',';
- /* Dump the length of the content of a block */
- num = snbid ? len : 0;
- COUNT_TRAILING_ZERO(num, work_char_ptr, trail_zero);
- num = snbid ? len : 0;
- OUTPUT_NUMBER(num, work_char_ptr, trail_zero);
- *work_char_ptr++ = ')';
+ /* Dump the length of the content of a block */
+ num = snbid ? len : 0;
+ COUNT_TRAILING_ZERO(num, work_char_ptr, trail_zero);
+ num = snbid ? len : 0;
+ OUTPUT_NUMBER(num, work_char_ptr, trail_zero);
+ *work_char_ptr++ = ')';
+ }
}
assert(MAX_ZWR_KEY_SZ >= work_char_ptr - work_buff);
if (GLO_FMT == dse_dmp_format)
diff --git a/sr_port/dse_getblk.c b/sr_port/dse_getblk.c
new file mode 100644
index 0000000..bde94b9
--- /dev/null
+++ b/sr_port/dse_getblk.c
@@ -0,0 +1,52 @@
+/****************************************************************
+ * *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include "gtm_string.h"
+#include "gdsroot.h"
+#include "gtm_facility.h"
+#include "fileinfo.h"
+#include "gdsbt.h"
+#include "gdsfhead.h"
+#include "gdsblk.h"
+#include "cli.h"
+#include "dse.h"
+#include "gtmmsg.h"
+
+GBLREF block_id patch_curr_blk;
+GBLREF gd_region *gv_cur_region;
+GBLREF sgmnt_addrs *cs_addrs;
+
+error_def(ERR_BLKINVALID);
+error_def(ERR_CANTBITMAP);
+
+block_id dse_getblk(char *element, boolean_t nobml, boolean_t carry_curr)
+{
+ block_id blk;
+
+ if (!cli_get_hex(element, (uint4 *)&blk))
+ blk = patch_curr_blk;
+ if ((blk < 0) || (blk >= cs_addrs->ti->total_blks))
+ {
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_BLKINVALID, 4, blk, DB_LEN_STR(gv_cur_region),
+ cs_addrs->ti->total_blks);
+ return BADDSEBLK;
+ }
+ if (nobml && IS_BITMAP_BLK(blk))
+ {
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CANTBITMAP);
+ return BADDSEBLK;
+ }
+ if (carry_curr)
+ patch_curr_blk = blk;
+ return blk;
+}
diff --git a/sr_port/dse_getki.c b/sr_port/dse_getki.c
index aeac302..c5d5ff3 100644
--- a/sr_port/dse_getki.c
+++ b/sr_port/dse_getki.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -120,8 +120,8 @@ int dse_getki(char *dst, int *len, char *qual, int qual_len)
}
} else if ('#' == *src)
{ /*Special spanning global subscript*/
- if ('S' != toupper(*(src + 1)) && 'P' != toupper(*(src + 2))
- && 'A' != toupper(*(src + 3)) && 'N' != toupper(*(src + 4)))
+ if ('S' != TOUPPER(*(src + 1)) && 'P' != TOUPPER(*(src + 2))
+ && 'A' != TOUPPER(*(src + 3)) && 'N' != TOUPPER(*(src + 4)))
{
util_out_print("Error: invalid key.", TRUE);
return FALSE;
@@ -211,7 +211,6 @@ int parse_dlr_char(char *src, char *top, char *dlr_subsc)
boolean_t dlrzchar = FALSE;
tmp_buf = src;
-
if ('Z' == TOUPPER(*tmp_buf))
{
dlrzchar = TRUE;
@@ -229,10 +228,8 @@ int parse_dlr_char(char *src, char *top, char *dlr_subsc)
}
else
tmp_buf += STR_LIT_LEN("har");
-
} else if (dlrzchar)
return 0;
-
if (*tmp_buf++ != '(')
return 0;
if (!ISDIGIT_ASCII(*tmp_buf))
@@ -253,14 +250,14 @@ int parse_dlr_char(char *src, char *top, char *dlr_subsc)
return 0;
*dlr_subsc++ = dlr_val;
}
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
else {
strnext = (char *)UTF8_WCTOMB(dlr_val, dlr_subsc);
if (strnext == dlr_subsc)
return 0;
dlr_subsc = strnext;
}
-#endif
+# endif
indx = 0;
if (')' == *tmp_buf)
{
diff --git a/sr_port/dse_integ.c b/sr_port/dse_integ.c
index 2813033..18a3c2e 100644
--- a/sr_port/dse_integ.c
+++ b/sr_port/dse_integ.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -27,9 +27,8 @@
#include "t_qread.h"
#include "cert_blk.h"
-GBLREF sgmnt_addrs *cs_addrs;
GBLREF gd_region *gv_cur_region;
-GBLREF block_id patch_curr_blk;
+GBLREF sgmnt_addrs *cs_addrs;
error_def(ERR_DSEBLKRDFAIL);
@@ -38,27 +37,18 @@ error_def(ERR_DSEBLKRDFAIL);
void dse_integ(void)
{
block_id blk;
- char util_buff[MAX_UTIL_LEN];
- sm_uc_ptr_t bp;
- int4 dummy_int, nocrit_present;
+ boolean_t was_crit, was_hold_onto_crit;
cache_rec_ptr_t dummy_cr;
+ char util_buff[MAX_UTIL_LEN];
int util_len;
- boolean_t was_crit, was_hold_onto_crit;
+ int4 dummy_int, nocrit_present;
+ sm_uc_ptr_t bp;
- if (CLI_PRESENT == cli_present("BLOCK"))
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- if (blk < 0 || blk >= cs_addrs->ti->total_blks)
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
- patch_curr_blk = blk;
- }
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSEBMLOK, DSEBLKCUR))) /* WARNING: assignment */
+ return;
memcpy(util_buff, "!/Checking integrity of block ", 30);
util_len = 30;
- util_len += i2hex_nofill(patch_curr_blk, (uchar_ptr_t)&util_buff[util_len], 8);
+ util_len += i2hex_nofill(blk, (uchar_ptr_t)&util_buff[util_len], 8);
memcpy(&util_buff[util_len], ":", 1);
util_len += 1;
util_buff[util_len] = 0;
@@ -66,9 +56,9 @@ void dse_integ(void)
was_crit = cs_addrs->now_crit;
nocrit_present = (CLI_NEGATED == cli_present("CRIT"));
DSE_GRAB_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- if (!(bp = t_qread(patch_curr_blk, &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
- if (TRUE == cert_blk(gv_cur_region, patch_curr_blk, (blk_hdr_ptr_t)bp, 0, FALSE))
+ if (!(bp = t_qread(blk, &dummy_int, &dummy_cr)))
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ if (TRUE == cert_blk(gv_cur_region, blk, (blk_hdr_ptr_t)bp, 0, FALSE))
util_out_print("!/ No errors detected.!/", TRUE);
else
util_out_print(NULL, TRUE);
diff --git a/sr_port/dse_is_blk_free.c b/sr_port/dse_is_blk_free.c
index 617ed1e..52b4dea 100644
--- a/sr_port/dse_is_blk_free.c
+++ b/sr_port/dse_is_blk_free.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -20,28 +20,21 @@
#include "dse.h"
/* Include prototypes */
-#include "dse_is_blk_free.h"
#include "t_qread.h"
GBLREF sgmnt_addrs *cs_addrs;
-bool dse_is_blk_free (block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr)
+error_def(ERR_DSEBLKRDFAIL);
+
+boolean_t dse_is_blk_free (block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr)
{
- uint4 status;
- uint4 index, offset;
sm_uc_ptr_t bp;
- error_def(ERR_DSEBLKRDFAIL);
+ uint4 index, offset, status;
index = (blk / cs_addrs->hdr->bplmap) * cs_addrs->hdr->bplmap;
offset = blk - index;
-
if(!(bp = t_qread (index, cycle, cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
-
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
status = dse_lm_blk_free(offset * BML_BITS_PER_BLK, bp + SIZEOF(blk_hdr));
- if (0 == status) /* status == 00 => blk is busy */
- return FALSE;
- else /* status == 01 and 11 => blk is free.
- Also illegal value is considered as free */
- return TRUE;
+ return (0 != status); /* status == 00 => busy; 01, 11, 10 (not currently legal) => free */
}
diff --git a/sr_port/dse_is_blk_in.c b/sr_port/dse_is_blk_in.c
index 7ae6324..f6a3a38 100644
--- a/sr_port/dse_is_blk_in.c
+++ b/sr_port/dse_is_blk_in.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,20 +22,16 @@
#include "dsefind.h"
#include "dse.h"
+GBLREF block_id patch_find_blk, patch_path[MAX_BT_DEPTH + 1], patch_path1[MAX_BT_DEPTH + 1];
+GBLREF boolean_t patch_find_root_search;
+GBLREF int4 patch_offset[MAX_BT_DEPTH + 1], patch_offset1[MAX_BT_DEPTH + 1];
+GBLREF short int patch_dir_path_count, patch_path_count;
GBLREF sgmnt_addrs *cs_addrs;
-GBLREF short int patch_dir_path_count;
-GBLREF block_id patch_find_blk;
-GBLREF bool patch_find_root_search;
-GBLREF int4 patch_offset[MAX_BT_DEPTH + 1];
-GBLREF int4 patch_offset1[MAX_BT_DEPTH + 1];
-GBLREF block_id patch_path[MAX_BT_DEPTH + 1];
-GBLREF block_id patch_path1[MAX_BT_DEPTH + 1];
-GBLREF short int patch_path_count;
int dse_is_blk_in(sm_uc_ptr_t rp, sm_uc_ptr_t r_top, short size)
{
- sm_uc_ptr_t key_top;
char targ_key[MAX_KEY_SZ + 1];
+ sm_uc_ptr_t key_top;
memcpy(targ_key, rp + SIZEOF(rec_hdr), size);
if ((patch_find_blk != patch_path[0])
diff --git a/sr_port/dse_ksrch.c b/sr_port/dse_ksrch.c
index 03953e2..029780a 100644
--- a/sr_port/dse_ksrch.c
+++ b/sr_port/dse_ksrch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -26,12 +26,13 @@
#include "t_qread.h"
#include "mmemory.h"
+GBLDEF block_id ksrch_root;
+
+GBLREF boolean_t patch_find_root_search;
+GBLREF char patch_comp_key[MAX_KEY_SZ + 1];
GBLREF short int patch_path_count;
GBLREF sgmnt_addrs *cs_addrs;
-GBLREF char patch_comp_key[MAX_KEY_SZ + 1];
GBLREF unsigned short patch_comp_count;
-GBLREF bool patch_find_root_search;
-GBLDEF block_id ksrch_root;
error_def(ERR_DSEBLKRDFAIL);
@@ -41,15 +42,12 @@ int dse_ksrch(block_id srch,
char *targ_key,
int targ_len)
{
- sm_uc_ptr_t bp, b_top, rp, r_top, key_top, blk_id;
- unsigned short cc;
- int tmp_cmpc;
- int rsize;
- ssize_t size;
- int4 cmp;
- unsigned short dummy_short;
- int4 dummy_int;
cache_rec_ptr_t dummy_cr;
+ int rsize, tmp_cmpc;
+ int4 cmp, dummy_int;
+ ssize_t size;
+ sm_uc_ptr_t blk_id, bp, b_top, key_top, rp, r_top;
+ unsigned short cc, dummy_short;
if(!(bp = t_qread(srch, &dummy_int, &dummy_cr)))
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
@@ -73,8 +71,6 @@ int dse_ksrch(block_id srch,
r_top = rp + rsize;
if (r_top > b_top)
r_top = b_top;
-
-
if (r_top - rp < (((blk_hdr_ptr_t)bp)->levl ? SIZEOF(block_id) : MIN_DATA_SIZE) + SIZEOF(rec_hdr))
{
*pp = 0;
@@ -83,7 +79,6 @@ int dse_ksrch(block_id srch,
for (key_top = rp + SIZEOF(rec_hdr); key_top < r_top ; )
if (!*key_top++ && !*key_top++)
break;
-
if (((blk_hdr_ptr_t)bp)->levl && key_top > (blk_id = r_top - SIZEOF(block_id)))
key_top = blk_id;
if (EVAL_CMPC((rec_hdr_ptr_t)rp) > patch_comp_count)
diff --git a/sr_port/dse_maps.c b/sr_port/dse_maps.c
index e69085f..607186e 100644
--- a/sr_port/dse_maps.c
+++ b/sr_port/dse_maps.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -37,7 +37,6 @@
/* Include prototypes */
#include "t_qread.h"
-#include "dse_is_blk_free.h"
#include "bit_set.h"
#include "bit_clear.h"
#include "t_begin_crit.h"
@@ -50,15 +49,14 @@
#define MAX_UTIL_LEN 80
-GBLREF char *update_array, *update_array_ptr;
-GBLREF uint4 update_array_size;
-GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF block_id patch_curr_blk;
-GBLREF gd_region *gv_cur_region;
-GBLREF short crash_count;
-GBLREF boolean_t unhandled_stale_timer_pop;
+GBLREF boolean_t unhandled_stale_timer_pop;
+GBLREF char *update_array, *update_array_ptr;
+GBLREF gd_region *gv_cur_region;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF short crash_count;
GBLREF srch_hist dummy_hist;
+GBLREF uint4 update_array_size;
error_def(ERR_DBRDONLY);
error_def(ERR_DSEBLKRDFAIL);
@@ -67,126 +65,44 @@ error_def(ERR_DSEFAIL);
void dse_maps(void)
{
- block_id blk, bml_blk;
blk_segment *bs1, *bs_ptr;
- int4 blk_seg_cnt, blk_size; /* needed for BLK_INIT, BLK_SEG and BLK_FINI macros */
- sm_uc_ptr_t bp;
+ block_id blk, bml_blk;
+ boolean_t was_crit;
+ cache_rec_ptr_t dummy_cr;
char util_buff[MAX_UTIL_LEN];
- int4 bml_size, bml_list_size, blk_index, bml_index;
- int4 total_blks, blks_in_bitmap;
- int4 bplmap, dummy_int;
- unsigned char *bml_list;
- cache_rec_ptr_t cr, dummy_cr;
- bt_rec_ptr_t btr;
int util_len;
- uchar_ptr_t blk_ptr;
- boolean_t was_crit;
- uint4 jnl_status;
- srch_blk_status blkhist;
- jnl_private_control *jpc;
- jnl_buffer_ptr_t jbp;
+ int4 blk_seg_cnt, blk_size; /* needed for BLK_INIT, BLK_SEG and BLK_FINI macros */
+ sm_uc_ptr_t bp;
+ int4 blk_index, blks_in_bitmap, bml_index, bml_list_size, bml_size, bplmap, dummy_int, total_blks;
sgmnt_addrs *csa;
sgmnt_data_ptr_t csd;
+ srch_blk_status blkhist;
+ uchar_ptr_t blk_ptr;
+ unsigned char *bml_list;
+ csa = cs_addrs;
if (CLI_PRESENT == cli_present("BUSY") || CLI_PRESENT == cli_present("FREE") ||
CLI_PRESENT == cli_present("MASTER") || CLI_PRESENT == cli_present("RESTORE_ALL"))
{
- if (gv_cur_region->read_only)
- rts_error(VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
+ if (gv_cur_region->read_only)
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
}
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
- csa = cs_addrs;
assert(&FILE_INFO(gv_cur_region)->s_addrs == csa);
was_crit = csa->now_crit;
if (csa->critical)
crash_count = csa->critical->crashcnt;
csd = csa->hdr;
+ assert(csd == cs_data);
bplmap = csd->bplmap;
- if (CLI_PRESENT == cli_present("BLOCK"))
+ if (0 == bplmap)
{
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- if (blk < 0 || blk >= csa->ti->total_blks)
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
- patch_curr_blk = blk;
- }
- else
- blk = patch_curr_blk;
- if (CLI_PRESENT == cli_present("FREE"))
- {
- if (0 == bplmap)
- {
- util_out_print("Cannot perform map updates: bplmap field of file header is zero.", TRUE);
- return;
- }
- if (blk / bplmap * bplmap == blk)
- {
- util_out_print("Cannot perform action on a map block.", TRUE);
- return;
- }
- bml_blk = blk / bplmap * bplmap;
- bm_setmap(bml_blk, blk, FALSE);
- return;
- }
- if (CLI_PRESENT == cli_present("BUSY"))
- {
- if (0 == bplmap)
- {
- util_out_print("Cannot perform map updates: bplmap field of file header is zero.", TRUE);
- return;
- }
- if (blk / bplmap * bplmap == blk)
- {
- util_out_print("Cannot perform action on a map block.", TRUE);
- return;
- }
- bml_blk = blk / bplmap * bplmap;
- bm_setmap(bml_blk, blk, TRUE);
+ util_out_print("Cannot perform map updates: bplmap field of file header is zero.", TRUE);
return;
}
blk_size = csd->blk_size;
- if (CLI_PRESENT == cli_present("MASTER"))
- {
- if (0 == bplmap)
- {
- util_out_print("Cannot perform maps updates: bplmap field of file header is zero.", TRUE);
- return;
- }
- if (!was_crit)
- grab_crit(gv_cur_region);
- bml_blk = blk / bplmap * bplmap;
- if (dba_mm == csd->acc_meth)
- bp = MM_BASE_ADDR(csa) + (off_t)bml_blk * blk_size;
- else
- {
- assert(dba_bg == csd->acc_meth);
- if (!(bp = t_qread(bml_blk, &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
- }
- if ((csa->ti->total_blks / bplmap) * bplmap == bml_blk)
- total_blks = (csa->ti->total_blks - bml_blk);
- else
- total_blks = bplmap;
- if (NO_FREE_SPACE == bml_find_free(0, bp + SIZEOF(blk_hdr), total_blks))
- bit_clear(bml_blk / bplmap, csa->bmm);
- else
- bit_set(bml_blk / bplmap, csa->bmm);
- if (bml_blk > csa->nl->highest_lbm_blk_changed)
- csa->nl->highest_lbm_blk_changed = bml_blk;
- if (!was_crit)
- rel_crit(gv_cur_region);
- return;
- }
if (CLI_PRESENT == cli_present("RESTORE_ALL"))
{
- if (0 == bplmap)
- {
- util_out_print("Cannot perform maps updates: bplmap field of file header is zero.", TRUE);
- return;
- }
total_blks = csa->ti->total_blks;
assert(ROUND_DOWN2(blk_size, 2 * SIZEOF(int4)) == blk_size);
bml_size = BM_SIZE(bplmap);
@@ -215,13 +131,13 @@ void dse_maps(void)
blk_ptr = bml_list + bml_index * bml_size;
blkhist.blk_num = blk_index;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
BLK_INIT(bs_ptr, bs1);
BLK_SEG(bs_ptr, blk_ptr + SIZEOF(blk_hdr), bml_size - SIZEOF(blk_hdr));
BLK_FINI(bs_ptr, bs1);
t_write(&blkhist, (unsigned char *)bs1, 0, 0, LCL_MAP_LEVL, TRUE, FALSE, GDS_WRITE_KILLTN);
BUILD_AIMG_IF_JNL_ENABLED(csd, csa->ti->curr_tn);
- t_end(&dummy_hist, NULL, csa->ti->curr_tn);
+ t_end(&dummy_hist, NULL, TN_NOT_SPECIFIED);
}
/* Fill in master map */
for (blk_index = 0, bml_index = 0; blk_index < total_blks; blk_index += bplmap, bml_index++)
@@ -246,6 +162,49 @@ void dse_maps(void)
csd->kill_in_prog = csd->abandoned_kills = 0;
return;
}
+ if (CLI_PRESENT == cli_present("FREE"))
+ {
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSENOBML, DSEBLKCUR))) /* WARNING: assignment */
+ return;
+ bml_blk = blk / bplmap * bplmap;
+ bm_setmap(bml_blk, blk, FALSE);
+ return;
+ }
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSEBMLOK, DSEBLKCUR))) /* WARNING: assignment */
+ return;
+ if (CLI_PRESENT == cli_present("BUSY"))
+ {
+ bml_blk = blk / bplmap * bplmap;
+ bm_setmap(bml_blk, blk, TRUE);
+ return;
+ }
+ if (CLI_PRESENT == cli_present("MASTER"))
+ {
+ if (!was_crit)
+ grab_crit(gv_cur_region);
+ bml_blk = blk / bplmap * bplmap;
+ if (dba_mm == csd->acc_meth)
+ bp = MM_BASE_ADDR(csa) + (off_t)bml_blk * blk_size;
+ else
+ {
+ assert(dba_bg == csd->acc_meth);
+ if (!(bp = t_qread(bml_blk, &dummy_int, &dummy_cr)))
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ }
+ if ((csa->ti->total_blks / bplmap) * bplmap == bml_blk)
+ total_blks = (csa->ti->total_blks - bml_blk);
+ else
+ total_blks = bplmap;
+ if (NO_FREE_SPACE == bml_find_free(0, bp + SIZEOF(blk_hdr), total_blks))
+ bit_clear(bml_blk / bplmap, csa->bmm);
+ else
+ bit_set(bml_blk / bplmap, csa->bmm);
+ if (bml_blk > csa->nl->highest_lbm_blk_changed)
+ csa->nl->highest_lbm_blk_changed = bml_blk;
+ if (!was_crit)
+ rel_crit(gv_cur_region);
+ return;
+ }
MEMCPY_LIT(util_buff, "!/Block ");
util_len = SIZEOF("!/Block ") - 1;
util_len += i2hex_nofill(blk, (uchar_ptr_t)&util_buff[util_len], 8);
diff --git a/sr_port/dse_order.c b/sr_port/dse_order.c
index 55fd131..4156f25 100644
--- a/sr_port/dse_order.c
+++ b/sr_port/dse_order.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -26,10 +26,10 @@
#include "t_qread.h"
#include "mmemory.h"
-GBLREF char patch_comp_key[MAX_KEY_SZ + 1];
GBLREF block_id patch_find_blk, patch_left_sib, patch_right_sib;
GBLREF block_id patch_path[MAX_BT_DEPTH + 1], patch_path1[MAX_BT_DEPTH + 1];
-GBLREF bool patch_find_root_search;
+GBLREF boolean_t patch_find_root_search;
+GBLREF char patch_comp_key[MAX_KEY_SZ + 1];
GBLREF sgmnt_addrs *cs_addrs;
GBLREF short int patch_path_count;
GBLREF unsigned short patch_comp_count;
@@ -43,18 +43,17 @@ int dse_order(block_id srch,
short int targ_len,
bool dir_data_blk)
{
- sm_uc_ptr_t bp, b_top, key_top, ptr, rp, r_top;
- unsigned short cc;
- int tmp_cmpc;
block_id last;
- short int rsize, size;
- int4 dummy_int;
cache_rec_ptr_t dummy_cr;
+ int4 dummy_int;
+ short int rsize, size;
+ sm_uc_ptr_t bp, b_top, key_top, ptr, rp, r_top;
+ unsigned short cc;
last = 0;
patch_path_count++;
if (!(bp = t_qread(srch, &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
if (((blk_hdr_ptr_t)bp)->bsiz > cs_addrs->hdr->blk_size)
b_top = bp + cs_addrs->hdr->blk_size;
else if (SIZEOF(blk_hdr) > ((blk_hdr_ptr_t)bp)->bsiz)
diff --git a/sr_port/dse_over.c b/sr_port/dse_over.c
index 68a4f57..10f46a7 100644
--- a/sr_port/dse_over.c
+++ b/sr_port/dse_over.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,70 +42,60 @@
#include "stringpool.h"
#include "gtm_conv.h"
#include "gtm_utf8.h"
+#include "gtmmsg.h"
GBLREF char *update_array, *update_array_ptr;
+GBLREF cw_set_element cw_set[];
GBLREF gd_region *gv_cur_region;
-GBLREF uint4 update_array_size;
-GBLREF srch_hist dummy_hist;
-GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF block_id patch_curr_blk;
GBLREF gtm_chset_t dse_over_chset;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF spdesc stringpool;
+GBLREF srch_hist dummy_hist;
+GBLREF UConverter *chset_desc[];
+GBLREF uint4 update_array_size;
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
GBLREF iconv_t dse_over_cvtcd;
#endif
-GBLREF cw_set_element cw_set[];
-GBLREF UConverter *chset_desc[];
-GBLREF spdesc stringpool;
LITREF mstr chset_names[];
+error_def(ERR_AIMGBLKFAIL);
error_def(ERR_DBRDONLY);
error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_DSEFAIL);
void dse_over(void)
{
- static char *data = NULL;
+ static char *data = NULL;
static int data_size;
- block_id blk;
- uchar_ptr_t lbp;
- uint4 offset;
- int data_len, size;
+
blk_segment *bs1, *bs_ptr;
+ block_id blk;
+ char chset_name[MAX_CHSET_NAME];
+ int cvt_len, data_len, size;
int4 blk_seg_cnt, blk_size;
- unsigned char *cvt_src_ptr, *cvt_dst_ptr;
- unsigned int insize, outsize;
- char chset_name[MAX_CHSET_NAME];
- mstr chset_mstr;
- unsigned short name_len = 0;
+ mstr chset_mstr, cvt_src;
srch_blk_status blkhist;
- mstr cvt_src;
- int cvt_len;
+ uchar_ptr_t lbp;
+ uint4 offset;
+ unsigned char *cvt_src_ptr, *cvt_dst_ptr;
+ unsigned int insize, outsize;
+ unsigned short name_len = 0;
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
blk_size = cs_addrs->hdr->blk_size;
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- if (blk < 0 || blk >= cs_addrs->ti->total_blks)
- {
- util_out_print("Error: invalid block number.",TRUE);
- return;
- }
- patch_curr_blk = blk;
- } else
- blk = patch_curr_blk;
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSEBMLOK, DSEBLKCUR))) /* WARNING: assignment */
+ return;
if (CLI_PRESENT == cli_present("OCHSET"))
{
name_len = SIZEOF(chset_name);
if (cli_get_str("OCHSET", chset_name, &name_len) && 0 != name_len)
{
chset_name[name_len] = 0;
-#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
+# if defined(KEEP_zOS_EBCDIC) || defined(VMS)
if ( (iconv_t)0 != dse_over_cvtcd )
{
ICONV_CLOSE_CD(dse_over_cvtcd);
@@ -114,26 +104,26 @@ void dse_over(void)
dse_over_cvtcd = (iconv_t)0;
else
ICONV_OPEN_CD(dse_over_cvtcd, INSIDE_CH_SET, chset_name);
-#else
+# else
chset_mstr.addr = chset_name;
chset_mstr.len = name_len;
SET_ENCODING(dse_over_chset, &chset_mstr);
get_chset_desc(&chset_names[dse_over_chset]);
-#endif
+# endif
}
} else
{
-#ifdef KEEP_zOS_EBCDIC
+# ifdef KEEP_zOS_EBCDIC
if ((iconv_t)0 != dse_over_cvtcd )
{
ICONV_CLOSE_CD(dse_over_cvtcd);
dse_over_cvtcd = (iconv_t)0; /* default ASCII, no conversion */
}
-#else
+# else
dse_over_chset = CHSET_M;
-#endif
+# endif
}
- if (cli_present("OFFSET") != CLI_PRESENT)
+ if (CLI_PRESENT != cli_present("OFFSET"))
{
util_out_print("Error: offset must be specified.", TRUE);
return;
@@ -145,7 +135,7 @@ void dse_over(void)
util_out_print("Error: offset too small.", TRUE);
return;
}
- if (cli_present("DATA") != CLI_PRESENT)
+ if (CLI_PRESENT != cli_present("DATA"))
{
util_out_print("Error: data must be specified.", TRUE);
return;
@@ -154,13 +144,11 @@ void dse_over(void)
blkhist.blk_num = blk;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
-
size = ((blk_hdr_ptr_t)blkhist.buffaddr)->bsiz;
if (size < SIZEOF(blk_hdr))
size = SIZEOF(blk_hdr);
else if (size >= blk_size)
size = blk_size;
-
if (offset >= size)
{
util_out_print("Error: offset too large.", TRUE);
@@ -177,12 +165,12 @@ void dse_over(void)
t_abort(gv_cur_region, cs_addrs);
return;
}
-#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
+# if defined(KEEP_zOS_EBCDIC) || defined(VMS)
cvt_src_ptr = cvt_dst_ptr = (unsigned char *)data;
insize = outsize = (unsigned int)data_len;
if ((iconv_t)0 != dse_over_cvtcd)
ICONVERT(dse_over_cvtcd, &cvt_src_ptr, &insize, &cvt_dst_ptr, &outsize); /* in-place conversion */
-#else
+# else
cvt_src.len = (unsigned int)data_len;
cvt_src.addr = data;
if (CHSET_M != dse_over_chset)
@@ -197,7 +185,7 @@ void dse_over(void)
memcpy(data, stringpool.free, cvt_len);
data_len = cvt_len;
}
-#endif
+# endif
if (offset + data_len > size)
{
util_out_print("Error: data will not fit in block at given offset.", TRUE);
@@ -207,12 +195,11 @@ void dse_over(void)
lbp = (uchar_ptr_t)malloc(blk_size);
memcpy (lbp, blkhist.buffaddr, blk_size);
memcpy(lbp + offset, &data[0], data_len);
-
BLK_INIT(bs_ptr, bs1);
BLK_SEG(bs_ptr, (uchar_ptr_t)lbp + SIZEOF(blk_hdr), (int)((blk_hdr_ptr_t)lbp)->bsiz - SIZEOF(blk_hdr));
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, blk, DB_LEN_STR(gv_cur_region));
free(lbp);
t_abort(gv_cur_region, cs_addrs);
return;
diff --git a/sr_port/dse_r_dmp.c b/sr_port/dse_r_dmp.c
index e4aa2b0..6efbff3 100644
--- a/sr_port/dse_r_dmp.c
+++ b/sr_port/dse_r_dmp.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -28,43 +28,25 @@
/* Include prototypes */
#include "t_qread.h"
-GBLREF block_id patch_curr_blk;
-GBLREF sgmnt_addrs *cs_addrs;
GBLREF gd_region *gv_cur_region;
-GBLREF int patch_is_fdmp;
-GBLREF int patch_fdmp_recs;
-GBLREF int patch_rec_counter;
+GBLREF int patch_is_fdmp, patch_rec_counter;
+GBLREF sgmnt_addrs *cs_addrs;
GBLREF VSIG_ATOMIC_T util_interrupt;
-error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_CTRLC);
+error_def(ERR_DSEBLKRDFAIL);
boolean_t dse_r_dmp(void)
{
block_id blk;
- sm_uc_ptr_t bp, b_top, rp;
- int4 count;
- int4 dummy_int;
- cache_rec_ptr_t dummy_cr;
- short record, size;
boolean_t was_crit, was_hold_onto_crit;
- int4 nocrit_present;
-
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- uint4 tmp_blk;
+ cache_rec_ptr_t dummy_cr;
+ int4 count, dummy_int, nocrit_present;
+ sm_uc_ptr_t bp, b_top, rp;
- if(!cli_get_hex("BLOCK", &tmp_blk))
- return FALSE;
- blk = (block_id)tmp_blk;
- if (blk < 0 || blk >= cs_addrs->ti->total_blks || !(blk % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
- return FALSE;
- }
- patch_curr_blk = blk;
- }
- if (cli_present("COUNT") == CLI_PRESENT)
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSENOBML, DSEBLKCUR))) /* WARNING: assignment */
+ return FALSE;
+ if (CLI_PRESENT == cli_present("COUNT"))
{
if (!cli_get_hex("COUNT", (uint4 *)&count))
return FALSE;
@@ -73,8 +55,8 @@ boolean_t dse_r_dmp(void)
was_crit = cs_addrs->now_crit;
nocrit_present = (CLI_NEGATED == cli_present("CRIT"));
DSE_GRAB_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- if (!(bp = t_qread(patch_curr_blk, &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ if (!(bp = t_qread(blk, &dummy_int, &dummy_cr)))
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
if (((blk_hdr_ptr_t) bp)->bsiz > cs_addrs->hdr->blk_size)
b_top = bp + cs_addrs->hdr->blk_size;
else if (((blk_hdr_ptr_t) bp)->bsiz < SIZEOF(blk_hdr))
@@ -87,7 +69,7 @@ boolean_t dse_r_dmp(void)
util_out_print("Error: cannot perform GLO/ZWR dump on index block.", TRUE);
return FALSE;
}
- if (cli_present("RECORD") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("RECORD"))
{
if (!(rp = skan_rnum (bp, FALSE)))
{
@@ -102,14 +84,14 @@ boolean_t dse_r_dmp(void)
util_out_print(0, TRUE);
for ( ; 0 < count; count--)
{
- if (util_interrupt || !(rp = dump_record(rp, patch_curr_blk, bp, b_top)))
+ if (util_interrupt || !(rp = dump_record(rp, blk, bp, b_top)))
break;
patch_rec_counter += 1;
}
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
if (util_interrupt)
- rts_error(VARLSTCNT(1) ERR_CTRLC);
- else if (cli_present("HEADER") == CLI_NEGATED)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
+ else if (CLI_NEGATED == cli_present("HEADER"))
util_out_print(0, TRUE);
return TRUE;
}
diff --git a/sr_port/dse_range.c b/sr_port/dse_range.c
index 8b27067..210dbd9 100644
--- a/sr_port/dse_range.c
+++ b/sr_port/dse_range.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -30,82 +30,63 @@
/* Include prototypes */
#include "t_qread.h"
-#define MAX_UTIL_LEN 20
-
-GBLREF sgmnt_addrs *cs_addrs;
+GBLREF block_id patch_find_blk, patch_path[MAX_BT_DEPTH + 1];
+GBLREF boolean_t patch_find_root_search;
GBLREF gd_region *gv_cur_region;
-GBLREF VSIG_ATOMIC_T util_interrupt;
-GBLREF block_id patch_find_blk;
-GBLREF block_id patch_path[MAX_BT_DEPTH + 1];
GBLREF short int patch_path_count;
-GBLREF bool patch_find_root_search;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF VSIG_ATOMIC_T util_interrupt;
-error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_CTRLC);
+error_def(ERR_DSEBLKRDFAIL);
void dse_range(void)
{
- char lower[MAX_KEY_SZ + 1], targ_key[MAX_KEY_SZ + 1], upper[MAX_KEY_SZ + 1], util_buff[MAX_UTIL_LEN];
+ cache_rec_ptr_t dummy_cr;
+ char level, lower[MAX_KEY_SZ + 1], targ_key[MAX_KEY_SZ + 1], upper[MAX_KEY_SZ + 1];
block_id from, to, blk, blk_child;
- sm_uc_ptr_t bp, b_top, key_bot, key_top, key_top1, rp, r_top;
- char level;
+ boolean_t busy_matters, free, got_lonely_star, index, lost, low, star, up, was_crit, was_hold_onto_crit;
+ int cnt, dummy, lower_len, upper_len;
int4 dummy_int, nocrit_present;
- cache_rec_ptr_t dummy_cr;
short int rsize, size, size1;
- int cnt, dummy, lower_len, util_len, upper_len;
- boolean_t busy_matters, free, got_lonely_star, index, low, lost, star, up, was_crit, was_hold_onto_crit;
+ sm_uc_ptr_t bp, b_top, key_bot, key_top, key_top1, rp, r_top;
- if (cli_present("FROM") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("FROM"))
{
- if (!cli_get_hex("FROM", (uint4 *)&from))
- return;
- if (from < 0 || from > cs_addrs->ti->total_blks
- || !(from % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
- }
- else
+ if (BADDSEBLK == (from = dse_getblk("FROM", DSEBMLOK, DSEBLKNOCUR))) /* WARNING: assignment */
+ return;
+ } else
from = 1;
- if (cli_present("TO") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("TO"))
{
- if(!cli_get_hex("TO", (uint4 *)&to))
- return;
- if (to < 0 || to > cs_addrs->ti->total_blks
- || !(to % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
- }
- else
+ if (BADDSEBLK == (to = dse_getblk("TO", DSEBMLOK, DSEBLKNOCUR))) /* WARNING: assignment */
+ return;
+ } else
to = cs_addrs->ti->total_blks - 1;
- if (low = (cli_present("LOWER") == CLI_PRESENT))
+ if (low = (CLI_PRESENT == cli_present("LOWER"))) /* WARNING: assignment */
{
if (!dse_getki(&lower[0], &lower_len, LIT_AND_LEN("LOWER")))
return;
}
- if (up = (cli_present("UPPER") == CLI_PRESENT))
+ if (up = (CLI_PRESENT == cli_present("UPPER"))) /* WARNING: assignment */
{
if (!dse_getki(&upper[0], &upper_len, LIT_AND_LEN("UPPER")))
return;
}
- star = (cli_present("STAR") == CLI_PRESENT);
+ star = (CLI_PRESENT == cli_present("STAR"));
if (!low && !up && !star)
{
util_out_print("Must specify star, or a lower or upper key limit.", TRUE);
return;
}
- index = (cli_present("INDEX") == CLI_PRESENT);
- lost = (cli_present("LOST") == CLI_PRESENT);
+ index = (CLI_PRESENT == cli_present("INDEX"));
+ lost = (CLI_PRESENT == cli_present("LOST"));
dummy = cli_present("BUSY");
- if (dummy == CLI_PRESENT)
+ if (CLI_PRESENT == dummy)
{
busy_matters = TRUE;
free = FALSE;
- }
- else if (dummy == CLI_NEGATED)
+ } else if (CLI_NEGATED == dummy)
busy_matters = free = TRUE;
else
busy_matters = free = FALSE;
@@ -119,15 +100,15 @@ void dse_range(void)
if (util_interrupt)
{
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
- rts_error(VARLSTCNT(1) ERR_CTRLC);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
break;
}
if (!(blk % cs_addrs->hdr->bplmap))
continue;
if (!(bp = t_qread(blk, &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
level = ((blk_hdr_ptr_t)bp)->levl;
- if (index && (level == 0))
+ if (index && (0 == level))
continue;
if (busy_matters && (free != dse_is_blk_free(blk, &dummy_int, &dummy_cr)))
continue;
@@ -192,7 +173,7 @@ void dse_range(void)
{
blk_child = *(block_id_ptr_t)key_top;
if (!(bp = t_qread(blk_child, &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
if (((blk_hdr_ptr_t) bp)->bsiz > cs_addrs->hdr->blk_size)
b_top = bp + cs_addrs->hdr->blk_size;
else if (((blk_hdr_ptr_t) bp)->bsiz < SIZEOF(blk_hdr))
diff --git a/sr_port/dse_rest.c b/sr_port/dse_rest.c
index 3f89fde..9bfdd62 100644
--- a/sr_port/dse_rest.c
+++ b/sr_port/dse_rest.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -32,109 +32,124 @@
#include "t_write.h"
#include "t_end.h"
#include "t_begin_crit.h"
+#include "process_deferred_stale.h"
#include "gvcst_blk_build.h"
#include "t_abort.h"
+#include "gtmmsg.h"
#define MAX_UTIL_LEN 80
+GBLREF block_id patch_curr_blk;
GBLREF char *update_array, *update_array_ptr;
-GBLREF uint4 update_array_size;
-GBLREF srch_hist dummy_hist;
+GBLREF cw_set_element cw_set[];
+GBLREF gd_addr *original_header;
GBLREF gd_region *gv_cur_region;
-GBLREF block_id patch_curr_blk;
GBLREF save_strct patch_save_set[PATCH_SAVE_SIZE];
-GBLREF unsigned short int patch_save_count;
GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF gd_addr *original_header;
-GBLREF cw_set_element cw_set[];
+GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF srch_hist dummy_hist;
+GBLREF uint4 patch_save_count, update_array_size;
+error_def(ERR_AIMGBLKFAIL);
error_def(ERR_DBRDONLY);
error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_DSEFAIL);
+error_def(ERR_DSENOTOPEN);
+error_def(ERR_NOREGION);
void dse_rest(void)
{
+ blk_segment *bs1, *bs_ptr;
block_id to, from;
+ char util_buff[MAX_UTIL_LEN], rn[MAX_RN_LEN + 1];
+ gd_binding *map;
gd_region *region;
int i, util_len;
- uchar_ptr_t lbp;
- char util_buff[MAX_UTIL_LEN], rn[MAX_RN_LEN + 1];
- blk_segment *bs1, *bs_ptr;
int4 blk_seg_cnt, blk_size;
- unsigned short rn_len;
- uint4 version;
- gd_binding *map;
- boolean_t found;
srch_blk_status blkhist;
+ uchar_ptr_t lbp;
+ uint4 found_index, version;
+ unsigned short rn_len;
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
- if (cli_present("VERSION") != CLI_PRESENT)
+ if (cli_get_int("VERSION", (int4 *)&version))
{
- util_out_print("Error: save version number must be specified.", TRUE);
- return;
- }
- if (!cli_get_int("VERSION", (int4 *)&version))
- return;
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&to))
- return;
- if (to < 0 || to >= cs_addrs->ti->total_blks)
+ if (0 == version)
{
- util_out_print("Error: invalid block number.", TRUE);
+ util_out_print("Error: no such version.", TRUE);
return;
}
- patch_curr_blk = to;
} else
- to = patch_curr_blk;
- if (cli_present("FROM") == CLI_PRESENT)
- {
+ version = 0;
+ if (BADDSEBLK == (to = dse_getblk("BLOCK", DSEBMLOK, DSEBLKCUR))) /* WARNING: assignment */
+ return;
+ if (CLI_PRESENT == cli_present("FROM"))
+ { /* don't use dse_getblk because we're working out of the save set, not the db */
if (!cli_get_hex("FROM", (uint4 *)&from))
- return;
- if (from < 0 || from >= cs_addrs->ti->total_blks)
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
+ from = patch_curr_blk;
} else
from = to;
- if (cli_present("REGION") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("REGION"))
{
rn_len = SIZEOF(rn);
if (!cli_get_str("REGION", rn, &rn_len))
return;
- for (i = rn_len; i < MAX_RN_LEN + 1; i++)
+ for (i = 0; i < rn_len; i++)
+ rn[i] = TOUPPER(rn[i]); /* Region names are always upper-case ASCII and thoroughly NUL terminated */
+ for ( ; i < ARRAYSIZE(rn); i++)
rn[i] = 0;
- found = FALSE;
+ found_index = 0;
for (i = 0, region = original_header->regions; i < original_header->n_regions ;i++, region++)
- if (found = !memcmp(®ion->rname[0], &rn[0], MAX_RN_LEN))
+ if (found_index = !memcmp(®ion->rname[0], &rn[0], MAX_RN_LEN)) /* WARNING: assignment */
break;
- if (!found)
+ if (!found_index)
{
- util_out_print("Error: region not found.", TRUE);
- return;
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOREGION, 2, rn_len, rn);
+ return;
}
if (!region->open)
{
- util_out_print("Error: that region was not opened because it is not bound to any namespace.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DSENOTOPEN, 2, rn_len, rn);
return;
}
} else
- region = gv_cur_region;
- found = FALSE;
+ region = gv_cur_region;
+ found_index = 0;
for (i = 0; i < patch_save_count; i++)
{
- if ((patch_save_set[i].blk == from) && (patch_save_set[i].region == region)
- && (found = (version == patch_save_set[i].ver)))
- break;
+ if ((patch_save_set[i].blk == from) && (patch_save_set[i].region == region))
+ {
+ if (version == patch_save_set[i].ver)
+ {
+ assert(version);
+ found_index = i + 1;
+ break;
+ }
+ if (!version)
+ {
+ if (found_index)
+ {
+ util_out_print("Error: save version number must be specified.", TRUE);
+ return;
+ }
+ found_index = i + 1;
+ }
+ }
+ }
+ if (0 == found_index)
+ {
+ if (version)
+ util_out_print("Error: Version !UL of block !XL not found in set of saved blocks", TRUE, version, from);
+ else
+ util_out_print("Error: Block !XL not found in set of saved blocks", TRUE, from);
+ return;
}
- if (!found)
+ if (!version)
{
- util_out_print("Error: no such version.", TRUE);
- return;
+ i = found_index - 1;
+ version = patch_save_set[i].ver;
}
memcpy(util_buff, "!/Restoring block ", 18);
util_len = 18;
@@ -142,6 +157,7 @@ void dse_rest(void)
memcpy(&util_buff[util_len], " from version !UL", 17);
util_len += 17;
util_buff[util_len] = 0;
+ assert(ARRAYSIZE(util_buff) >= util_len);
util_out_print(util_buff, FALSE, version);
if (to != from)
{
@@ -149,14 +165,15 @@ void dse_rest(void)
util_len = 10;
util_len += i2hex_nofill(from, (uchar_ptr_t)&util_buff[util_len], 8);
util_buff[util_len] = 0;
+ assert(ARRAYSIZE(util_buff) >= util_len);
util_out_print(util_buff, FALSE);
}
if (region != gv_cur_region)
util_out_print(" in region !AD", FALSE, LEN_AND_STR(rn));
util_out_print("!/", TRUE);
- if (to > cs_addrs->ti->total_blks)
- rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
t_begin_crit(ERR_DSEFAIL);
+ if (to >= cs_addrs->ti->total_blks)
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
blk_size = cs_addrs->hdr->blk_size;
blkhist.blk_num = to;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
@@ -167,12 +184,11 @@ void dse_rest(void)
BLK_SEG(bs_ptr, (uchar_ptr_t)lbp + SIZEOF(blk_hdr), (int)((blk_hdr_ptr_t)lbp)->bsiz - SIZEOF(blk_hdr));
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, to, DB_LEN_STR(gv_cur_region));
t_abort(gv_cur_region, cs_addrs);
return;
}
t_write(&blkhist, (unsigned char *)bs1, 0, 0, ((blk_hdr_ptr_t)lbp)->levl, TRUE, FALSE, GDS_WRITE_KILLTN);
- BUILD_AIMG_IF_JNL_ENABLED(cs_data, cs_addrs->ti->curr_tn);
- t_end(&dummy_hist, NULL, TN_NOT_SPECIFIED);
+ BUILD_AIMG_IF_JNL_ENABLED_AND_T_END_WITH_EFFECTIVE_TN(cs_addrs, cs_data, ((blk_hdr_ptr_t)lbp)->tn, &dummy_hist);
return;
}
diff --git a/sr_port/dse_rmrec.c b/sr_port/dse_rmrec.c
index 59004f0..b1c81cb 100644
--- a/sr_port/dse_rmrec.c
+++ b/sr_port/dse_rmrec.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -38,50 +38,39 @@
#include "t_begin_crit.h"
#include "gvcst_blk_build.h"
#include "t_abort.h"
+#include "gtmmsg.h"
-GBLREF char *update_array, *update_array_ptr;
-GBLREF uint4 update_array_size;
-GBLREF gd_region *gv_cur_region;
-GBLREF srch_hist dummy_hist;
+GBLREF char patch_comp_key[MAX_KEY_SZ + 1], *update_array, *update_array_ptr;
+GBLREF cw_set_element cw_set[];
+GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF block_id patch_curr_blk;
-GBLREF char patch_comp_key[MAX_KEY_SZ + 1];
+GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF srch_hist dummy_hist;
+GBLREF uint4 update_array_size;
GBLREF unsigned short patch_comp_count;
-GBLREF cw_set_element cw_set[];
+error_def(ERR_AIMGBLKFAIL);
error_def(ERR_DBRDONLY);
error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_DSEFAIL);
void dse_rmrec(void)
{
- block_id blk;
blk_segment *bs1, *bs_ptr;
- int4 blk_seg_cnt, blk_size;
- int4 count;
- uchar_ptr_t lbp, b_top, rp, r_top, key_top, rp_base;
+ block_id blk;
char comp_key[MAX_KEY_SZ + 1];
- unsigned short cc, cc_base;
- int tmp_cmpc;
+ int4 blk_seg_cnt, blk_size, count;
short int size, i, rsize;
srch_blk_status blkhist;
+ uchar_ptr_t lbp, b_top, rp, r_top, key_top, rp_base;
+ unsigned short cc, cc_base;
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- if(!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- if (blk < 0 || blk >= cs_addrs->ti->total_blks || !(blk % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
- patch_curr_blk = blk;
- }
- if (cli_present("COUNT") == CLI_PRESENT)
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSENOBML, DSEBLKCUR))) /* WARNING: assignment */
+ return;
+ if (CLI_PRESENT == cli_present("COUNT"))
{
if (!cli_get_hex("COUNT", (uint4 *)&count) || count < 1)
return;
@@ -89,7 +78,7 @@ void dse_rmrec(void)
count = 1;
t_begin_crit(ERR_DSEFAIL);
blk_size = cs_addrs->hdr->blk_size;
- blkhist.blk_num = patch_curr_blk;
+ blkhist.blk_num = blk;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
lbp = (uchar_ptr_t)malloc(blk_size);
@@ -101,7 +90,7 @@ void dse_rmrec(void)
b_top = lbp + SIZEOF(blk_hdr);
else
b_top = lbp + ((blk_hdr_ptr_t)lbp)->bsiz;
- if (cli_present("RECORD") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("RECORD"))
{
if (!(rp = rp_base = skan_rnum(lbp, FALSE)))
{
@@ -136,7 +125,8 @@ void dse_rmrec(void)
(int)((blk_hdr_ptr_t)lbp)->bsiz - SIZEOF(blk_hdr));
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.",TRUE);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, blk,
+ DB_LEN_STR(gv_cur_region));
free(lbp);
t_abort(gv_cur_region, cs_addrs);
return;
@@ -187,7 +177,7 @@ void dse_rmrec(void)
BLK_SEG(bs_ptr, (uchar_ptr_t)lbp + SIZEOF(blk_hdr), ((blk_hdr_ptr_t)lbp)->bsiz - SIZEOF(blk_hdr));
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, blk, DB_LEN_STR(gv_cur_region));
free(lbp);
t_abort(gv_cur_region, cs_addrs);
return;
diff --git a/sr_port/dse_rmsb.c b/sr_port/dse_rmsb.c
index 0857dd4..621407a 100644
--- a/sr_port/dse_rmsb.c
+++ b/sr_port/dse_rmsb.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,50 +22,75 @@
#include "cli.h"
#include "util.h"
-GBLREF sgmnt_addrs *cs_addrs;
-GBLREF gd_region *gv_cur_region;
GBLREF block_id patch_curr_blk;
+GBLREF gd_region *gv_cur_region;
GBLREF save_strct patch_save_set[PATCH_SAVE_SIZE];
-GBLREF unsigned short patch_save_count;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF uint4 patch_save_count;
+
+#define MAX_UTIL_LEN 80
void dse_rmsb(void)
{
block_id blk;
+ char util_buff[MAX_UTIL_LEN];
+ int util_len;
+ uint4 found_index, version;
unsigned int i;
- uint4 version;
- bool found;
- if (cli_present("VERSION") != CLI_PRESENT)
+ if (cli_get_int("VERSION", (int4 *)&version))
{
- util_out_print("Error: save version number must be specified.", TRUE);
- return;
- }
- if (!cli_get_int("VERSION", (int4 *)&version))
- return;
- if (cli_present("BLOCK") == CLI_PRESENT)
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- if (blk < 0 || blk >= cs_addrs->ti->total_blks || !(blk % cs_addrs->hdr->bplmap))
+ if (0 == version)
{
- util_out_print("Error: invalid block number.", TRUE);
+ util_out_print("Error: no such version.", TRUE);
return;
}
- patch_curr_blk = blk;
+ } else
+ version = 0;
+ if (!cli_get_hex("BLOCK", (uint4 *)&blk)) /* don't use dse_getblk - working out of the save set, not the db */
+ blk = patch_curr_blk;
+ found_index = 0;
+ for (i = 0; i < patch_save_count; i++)
+ {
+ if ((patch_save_set[i].blk == blk) && (patch_save_set[i].region == gv_cur_region))
+ {
+ if (version == patch_save_set[i].ver)
+ {
+ assert(version);
+ found_index = i + 1;
+ break;
+ }
+ if (!version)
+ {
+ if (found_index)
+ {
+ util_out_print("Error: save version number must be specified.", TRUE);
+ return;
+ }
+ found_index = i + 1;
+ }
+ }
}
- found = FALSE;
- for (i = 0; i < patch_save_count; i++)
- if (patch_save_set[i].blk == patch_curr_blk && patch_save_set[i].region == gv_cur_region
- &&(found = version == patch_save_set[i].ver))
- break;
- if (!found)
+ if (0 == found_index)
{
- util_out_print("Error: no such version.", TRUE);
+ if (version)
+ util_out_print("Error: Version !UL of block !XL not found in set of saved blocks", TRUE, version, blk);
+ else
+ util_out_print("Error: Block !XL not found in set of saved blocks", TRUE, blk);
return;
}
- patch_save_count--;
+ if (!version)
+ {
+ i = found_index - 1;
+ version = patch_save_set[i].ver;
+ }
+ util_len = SIZEOF("!/Removing version !UL of block ");
+ memcpy(util_buff, "!/Removing version !UL of block ", util_len);
+ util_len += i2hex_nofill(blk, (uchar_ptr_t)&util_buff[util_len-1], 8);
+ util_buff[util_len-1] = 0;
+ assert(ARRAYSIZE(util_buff) >= util_len);
+ util_out_print(util_buff, TRUE, version);
free(patch_save_set[i].bp);
- memcpy(&patch_save_set[i], &patch_save_set[i + 1],
- (patch_save_count - i) * SIZEOF(save_strct));
+ memmove(&patch_save_set[i], &patch_save_set[i + 1], (--patch_save_count - i) * SIZEOF(save_strct));
return;
}
diff --git a/sr_port/dse_save.c b/sr_port/dse_save.c
index 46c5e50..d57f0fc 100644
--- a/sr_port/dse_save.c
+++ b/sr_port/dse_save.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,46 +22,36 @@
/* Include prototypes */
#include "t_qread.h"
+#include "gtmmsg.h"
+#define MAX_COMMENT_LEN 100
#define MAX_UTIL_LEN 80
GBLDEF save_strct patch_save_set[PATCH_SAVE_SIZE];
-GBLDEF unsigned short patch_save_count = 0;
+GBLDEF uint4 patch_save_count = 0;
-GBLREF sgmnt_addrs *cs_addrs;
GBLREF gd_region *gv_cur_region;
-GBLREF block_id patch_curr_blk;
+GBLREF sgmnt_addrs *cs_addrs;
error_def(ERR_DSEBLKRDFAIL);
+error_def(ERR_DSEMAXBLKSAV);
void dse_save(void)
{
block_id blk;
- unsigned i, j, util_len;
- unsigned short buff_len;
- boolean_t was_block, was_crit, was_hold_onto_crit;
- char buff[100], *ptr, util_buff[MAX_UTIL_LEN];
- sm_uc_ptr_t bp;
- int4 dummy_int, nocrit_present;
+ boolean_t was_crit, was_hold_onto_crit;
cache_rec_ptr_t dummy_cr;
+ char buff[MAX_COMMENT_LEN], *ptr, util_buff[MAX_UTIL_LEN];
+ int i, j, util_len;
+ int4 dummy_int, nocrit_present;
+ sm_uc_ptr_t bp;
+ unsigned short buff_len;
+ assert(PATCH_SAVE_SIZE < MAXUINT4);
memset(util_buff, 0, MAX_UTIL_LEN);
-
- if (was_block = (cli_present("BLOCK") == CLI_PRESENT))
- {
- if (!cli_get_hex("BLOCK", (uint4 *)&blk))
- return;
- if (blk < 0 || blk >= cs_addrs->ti->total_blks)
- {
- util_out_print("Error: invalid block number.", TRUE);
- return;
- }
- patch_curr_blk = blk;
- } else
- blk = patch_curr_blk;
- if (cli_present("LIST") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("LIST"))
{
- if (was_block)
+ if (cli_get_hex("BLOCK", (uint4 *)&blk))
{
util_len = SIZEOF("!/Saved versions of block ");
memcpy(util_buff, "!/Saved versions of block ", util_len);
@@ -72,12 +62,10 @@ void dse_save(void)
if (patch_save_set[i].blk == blk)
{
j++;
-
if (*patch_save_set[i].comment)
util_out_print("Version !UL Region !AD Comment: !AD!/", TRUE,
patch_save_set[i].ver, REG_LEN_STR(patch_save_set[i].region),
LEN_AND_STR(patch_save_set[i].comment));
-
else
util_out_print("Version !UL Region !AD!/", TRUE, patch_save_set[i].ver,
REG_LEN_STR(patch_save_set[i].region));
@@ -100,7 +88,6 @@ void dse_save(void)
util_out_print("Version !UL Region !AD Comment: !AD!/", TRUE,
patch_save_set[i].ver, REG_LEN_STR(patch_save_set[i].region),
LEN_AND_STR(patch_save_set[i].comment));
-
} else
{
util_out_print("Version !UL Region !AD!/", TRUE, patch_save_set[i].ver,
@@ -111,6 +98,13 @@ void dse_save(void)
util_out_print(" None.!/", TRUE);
return;
}
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSEBMLOK, DSEBLKCUR))) /* WARNING: assignment */
+ return;
+ if (ARRAYSIZE(patch_save_set) <= patch_save_count)
+ {
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_DSEMAXBLKSAV, 1, PATCH_SAVE_SIZE);
+ return;
+ }
j = 1;
for (i = 0; i < patch_save_count; i++)
if (patch_save_set[i].blk == blk && patch_save_set[i].region == gv_cur_region
@@ -120,22 +114,23 @@ void dse_save(void)
memcpy(util_buff, "!/Saving version !UL of block ", util_len);
util_len += i2hex_nofill(blk, (uchar_ptr_t)&util_buff[util_len-1], 8);
util_buff[util_len-1] = 0;
+ assert(ARRAYSIZE(util_buff) >= util_len);
util_out_print(util_buff, TRUE, j);
patch_save_set[patch_save_count].ver = j;
patch_save_set[patch_save_count].blk = blk;
patch_save_set[patch_save_count].region = gv_cur_region;
patch_save_set[patch_save_count].bp = (char *)malloc(cs_addrs->hdr->blk_size);
if (blk >= cs_addrs->ti->total_blks)
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
was_crit = cs_addrs->now_crit;
nocrit_present = (CLI_NEGATED == cli_present("CRIT"));
DSE_GRAB_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
if (!(bp = t_qread(blk, &dummy_int, &dummy_cr)))
- rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_DSEBLKRDFAIL);
memcpy(patch_save_set[patch_save_count].bp, bp, cs_addrs->hdr->blk_size);
DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region);
buff_len = SIZEOF(buff);
- if ((cli_present("COMMENT") == CLI_PRESENT) && cli_get_str("COMMENT", buff, &buff_len))
+ if ((CLI_PRESENT == cli_present("COMMENT")) && cli_get_str("COMMENT", buff, &buff_len))
{
ptr = &buff[buff_len];
*ptr = 0;
diff --git a/sr_port/dse_shift.c b/sr_port/dse_shift.c
index 04b6911..2cf29cc 100644
--- a/sr_port/dse_shift.c
+++ b/sr_port/dse_shift.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -36,40 +36,38 @@
#include "t_begin_crit.h"
#include "gvcst_blk_build.h"
#include "t_abort.h"
+#include "gtmmsg.h"
GBLREF char *update_array, *update_array_ptr;
+GBLREF cw_set_element cw_set[];
GBLREF gd_region *gv_cur_region;
-GBLREF uint4 update_array_size;
-GBLREF srch_hist dummy_hist;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF block_id patch_curr_blk;
-GBLREF cw_set_element cw_set[];
+GBLREF srch_hist dummy_hist;
+GBLREF uint4 update_array_size;
+error_def(ERR_AIMGBLKFAIL);
error_def(ERR_DBRDONLY);
error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_DSEFAIL);
void dse_shift(void)
{
- bool forward;
- uint4 offset, shift;
- int4 size;
- sm_uc_ptr_t bp;
- uchar_ptr_t lbp;
blk_segment *bs1, *bs_ptr;
- int4 blk_seg_cnt, blk_size;
+ block_id blk;
+ boolean_t forward;
+ int4 blk_seg_cnt, blk_size, size;
+ sm_uc_ptr_t bp;
srch_blk_status blkhist;
+ uchar_ptr_t lbp;
+ uint4 offset, shift;
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
- if (patch_curr_blk < 0 || patch_curr_blk >= cs_addrs->ti->total_blks || !(patch_curr_blk % cs_addrs->hdr->bplmap))
- {
- util_out_print("Error: invalid block number.", TRUE);
+ if (BADDSEBLK == (blk = dse_getblk("BLOCK", DSENOBML, DSEBLKCUR))) /* WARNING: assignment */
return;
- }
- if (cli_present("OFFSET") != CLI_PRESENT)
+ if (CLI_PRESENT != cli_present("OFFSET"))
{
util_out_print("Error: offset must be specified.", TRUE);
return;
@@ -77,13 +75,13 @@ void dse_shift(void)
if (!cli_get_hex("OFFSET", &offset))
return;
shift = 0;
- if (cli_present("FORWARD") == CLI_PRESENT)
+ if (CLI_PRESENT == cli_present("FORWARD"))
{
if (!cli_get_hex("FORWARD", &shift))
return;
forward = TRUE;
lbp = (unsigned char *)malloc((size_t)shift);
- } else if (cli_present("BACKWARD") == CLI_PRESENT)
+ } else if (CLI_PRESENT == cli_present("BACKWARD"))
{
if (!cli_get_hex("BACKWARD", &shift))
return;
@@ -104,7 +102,7 @@ void dse_shift(void)
}
blk_size = cs_addrs->hdr->blk_size;
t_begin_crit(ERR_DSEFAIL);
- blkhist.blk_num = patch_curr_blk;
+ blkhist.blk_num = blk;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
{
if (lbp)
@@ -152,7 +150,7 @@ void dse_shift(void)
}
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, blk, DB_LEN_STR(gv_cur_region));
t_abort(gv_cur_region, cs_addrs);
if (lbp)
free(lbp);
diff --git a/sr_port/entryref.c b/sr_port/entryref.c
index b05314f..e32b866 100644
--- a/sr_port/entryref.c
+++ b/sr_port/entryref.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -23,12 +23,53 @@
#include <rtnhdr.h>
#include "stack_frame.h"
+STATICFNDCL oprtype insert_extref(mident *rtnname);
+STATICFNDCL triple *insert_extref_fast(opctype op1, opctype op2, mident *rtnname, mident *labname);
+
+#define CONVERT_MUTIL_NAME_PERCENT_TO_UNDERSCORE(RTNNAME) \
+{ \
+ if ((RTNNAME)->addr[0] == '%') \
+ (RTNNAME)->addr[0] = '_'; \
+}
+#define IS_SAME_RTN(NAME1, NAME2) (MIDENT_EQ(NAME1, NAME2))
+
+#define INSERT_EXTREF_NOMORPH_AND_RETURN(RTNNAME) \
+{ \
+ oprtype routine, rte1; \
+ triple *ref; \
+ \
+ rte1 = put_str((RTNNAME)->addr, (RTNNAME)->len); \
+ CONVERT_MUTIL_NAME_PERCENT_TO_UNDERSCORE((RTNNAME)); \
+ routine = put_cdlt((RTNNAME)); \
+ ref = newtriple(OC_RHDADDR); \
+ ref->operand[0] = rte1; \
+ ref->operand[1] = routine; \
+ routine = put_tref(ref); \
+ return routine; \
+}
+
GBLREF stack_frame *frame_pointer;
GBLREF mident routine_name;
error_def(ERR_LABELEXPECTED);
error_def(ERR_RTNNAME);
+/* Compiler entry point to parse an entry ref generating the necessary triples for just the actual call (does not handle
+ * routine parameters).
+ *
+ * Parameters:
+ *
+ * op1 - Opcode to use if this is a local call (call within current routine).
+ * op2 - Opcode to use if this is, or needs to be treated as, an external call. This latter is for auto-relink so if a
+ * new version of a routine exists, we effectively treat it as an external call since the call goes to a different
+ * flavor of the routine.
+ * commargcode - What type of command this is for (code from indir_* enum in indir.h)
+ * can_commarg - Indicates whether or not routine is allowed to call commarg to deal with indirects. Currently the only
+ * routine to set this to false is m_zgoto.c since it already deals with indirects its own way.
+ * labref - Only TRUE for calls frome exfunc. When TRUE, label offsets are not allowed.
+ * textname - Only TRUE for ZGOTO related calls where the routine/label names are passed as text instead of resolved to
+ * linkage table entries.
+ */
triple *entryref(opctype op1, opctype op2, mint commargcode, boolean_t can_commarg, boolean_t labref, boolean_t textname)
{
oprtype offset, label, routine, rte1;
@@ -36,60 +77,61 @@ triple *entryref(opctype op1, opctype op2, mint commargcode, boolean_t can_comma
mident rtnname, labname;
mstr rtn_str, lbl_str;
triple *ref, *next, *rettrip;
- boolean_t same_rout;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
+ /* There is no current case where both can_commarg and textname parameters are TRUE. If they start to exist, the code in
+ * this routine needs to be revisited for proper operation as the textname conditions were assumed not to happen if
+ * can_commarg was FALSE (which it is in the one known use of textname TRUE - in m_zgoto). Assert this now.
+ */
+ assert(!(can_commarg && textname));
+ /* Initialize our routine and label identifier midents */
rtnname.len = labname.len = 0;
rtnname.addr = &rtn_text[0];
labname.addr = &lab_text[0];
- /* These cases don't currently exist but if they start to exist, the code in this
- * routine needs to be revisited for proper operation as the textname conditions
- * were assumed not to happen if can_commarg was FALSE (which it is in the one
- * known use of textname TRUE - in m_zgoto).
- */
- assert(!(can_commarg && textname));
+ /* Discover what sort of entryref we have */
switch (TREF(window_token))
{
- case TK_INTLIT:
- int_label();
- /* caution: fall through */
- case TK_IDENT:
- memcpy(labname.addr, (TREF(window_ident)).addr, (TREF(window_ident)).len);
- labname.len = (TREF(window_ident)).len;
- advancewindow();
- if ((TK_PLUS != TREF(window_token)) && (TK_CIRCUMFLEX != TREF(window_token)) && !IS_MCODE_RUNNING && can_commarg)
- {
- rettrip = newtriple(op1);
- rettrip->operand[0] = put_mlab(&labname);
- return rettrip;
- }
- label.oprclass = NO_REF;
- break;
- case TK_ATSIGN:
- if(!indirection(&label))
+ case TK_INTLIT:
+ int_label();
+ /* caution: fall through */
+ case TK_IDENT:
+ memcpy(labname.addr, (TREF(window_ident)).addr, (TREF(window_ident)).len);
+ labname.len = (TREF(window_ident)).len;
+ advancewindow();
+ if ((TK_PLUS != TREF(window_token)) && (TK_CIRCUMFLEX != TREF(window_token)) && !IS_MCODE_RUNNING
+ && can_commarg)
+ { /* Only label specified - implies current routine */
+ rettrip = newtriple(op1);
+ rettrip->operand[0] = put_mlab(&labname);
+ return rettrip;
+ }
+ label.oprclass = NO_REF;
+ break;
+ case TK_ATSIGN:
+ if(!indirection(&label))
+ return NULL;
+ if ((TK_PLUS != TREF(window_token)) && (TK_CIRCUMFLEX != TREF(window_token))
+ && (TK_COLON != TREF(window_token)) && can_commarg)
+ { /* Have a single indirect arg like @ARG - not @LBL^[@]rtn or @LBL+1, etc. */
+ rettrip = ref = maketriple(OC_COMMARG);
+ ref->operand[0] = label;
+ ref->operand[1] = put_ilit(commargcode);
+ ins_triple(ref);
+ return rettrip;
+ }
+ labname.len = 0;
+ break;
+ case TK_PLUS:
+ stx_error(ERR_LABELEXPECTED);
return NULL;
- if ((TK_PLUS != TREF(window_token)) && (TK_CIRCUMFLEX != TREF(window_token)) && (TK_COLON != TREF(window_token))
- && can_commarg)
- {
- rettrip = ref = maketriple(OC_COMMARG);
- ref->operand[0] = label;
- ref->operand[1] = put_ilit(commargcode);
- ins_triple(ref);
- return rettrip;
- }
- labname.len = 0;
- break;
- case TK_PLUS:
- stx_error(ERR_LABELEXPECTED);
- return NULL;
- default:
- labname.len = 0;
- label.oprclass = NO_REF;
- break;
+ default:
+ labname.len = 0;
+ label.oprclass = NO_REF;
+ break;
}
if (!labref && (TK_PLUS == TREF(window_token)))
- { /* Have line offset specified */
+ { /* Have line offset allowed and specified */
advancewindow();
if (EXPR_FAIL == expr(&offset, MUMPS_INT))
return NULL;
@@ -100,103 +142,69 @@ triple *entryref(opctype op1, opctype op2, mint commargcode, boolean_t can_comma
advancewindow();
switch (TREF(window_token))
{
- case TK_IDENT:
- MROUT2XTERN((TREF(window_ident)).addr, rtnname.addr, (TREF(window_ident)).len);
- rtn_str.len = rtnname.len = (TREF(window_ident)).len;
- rtn_str.addr = rtnname.addr;
- advancewindow();
- if (!IS_MCODE_RUNNING)
- { /* Triples for normal compiled code. */
- NON_USHBIN_ONLY(same_rout = (MIDENT_EQ(&rtnname, &routine_name) && can_commarg));
- /* On shared binary platforms, we support recursive relink, and it's possible for an old version
- * of a routine to invoke a different new version. Therefore, even if a label corresponds to the
- * current routine name, we need to treat this as an external reference.
- */
- if (!textname)
- { /* Resolve routine and label names to addresses for most calls */
- if (!label.oprclass && !offset.oprclass)
- { /* Do LABEL^RTN comes here (LABEL is *not* indirect) */
-# ifndef USHBIN_SUPPORTED
- if (same_rout)
- { /* Do LABEL^SAMERTN comes here.
- * On platforms where we don't support recursive relink, we can treat
- * Do LABEL^SAMERTN the same as Do LABEL, and morph this into a local call.
- */
- rettrip = newtriple(op1);
- rettrip->operand[0] = put_mlab(&labname);
+ case TK_IDENT:
+ MROUT2XTERN((TREF(window_ident)).addr, rtnname.addr, (TREF(window_ident)).len);
+ rtnname.len = (TREF(window_ident)).len;
+ advancewindow();
+ if (!IS_MCODE_RUNNING)
+ { /* Triples for normal compiled code. */
+ if (!textname)
+ { /* Triples for DO, GOTO, extrinsic functions ($$). Resolve routine and label names
+ * to addresses for most calls.
+ */
+ if ((NO_REF == label.oprclass) && (NO_REF == offset.oprclass))
+ { /* Do LABEL^RTN comes here (LABEL is *not* indirect *and* no offset) */
+ rettrip = insert_extref_fast(op1, op2, &rtnname, &labname);
+ return rettrip;
} else
-# endif
- { /* Create an external reference to LABEL^RTN */
+ /* Label or offset was indirect so can't use linkage table to address
+ * the pieces - and no autorelink either
+ */
+ routine = insert_extref(&rtnname);
+ } else
+ { /* Triples for ZGOTO. Pass routine and label names as text literals */
+ if ((NO_REF == label.oprclass) && (NO_REF == offset.oprclass))
+ { /* Both label and routine supplied but no offset */
rettrip = maketriple(op2);
- if (rtnname.addr[0] == '%')
- rtnname.addr[0] = '_';
- rettrip->operand[0] = put_cdlt(&rtn_str);
- mlabel2xtern(&lbl_str, &rtnname, &labname);
- rettrip->operand[1] = put_cdlt(&lbl_str);
+ rettrip->operand[0] = put_str(rtnname.addr, rtnname.len);
+ ref = newtriple(OC_PARAMETER);
+ ref->operand[0] = put_str(labname.addr, labname.len);
+ ref->operand[1] = put_ilit(0);
+ rettrip->operand[1] = put_tref(ref);
ins_triple(rettrip);
- }
- return rettrip;
- } else NON_USHBIN_ONLY(if (!same_rout))
- { /* Do @"LABEL"^RTN comes here (LABEL is indirect).
- * Exception: on non-USHBIN platforms, we morph Do @"LABEL"^SAMERTN into a local
- * call in the next else-block.
- */
- rte1 = put_str(rtn_str.addr, rtn_str.len);
- if (rtnname.addr[0] == '%')
- rtnname.addr[0] = '_';
- routine = put_cdlt(&rtn_str);
- ref = newtriple(OC_RHDADDR);
- ref->operand[0] = rte1;
- ref->operand[1] = routine;
- routine = put_tref(ref);
+ return rettrip;
+ } else
+ /* Routine only (no label - may have offset) */
+ routine = put_str(rtnname.addr, rtnname.len);
}
-# ifndef USHBIN_SUPPORTED
- else /* Do @"LABEL"^SAMERTN comes here. Again, morph into local call Do @"LABEL" */
- routine = put_tref(newtriple(OC_CURRHD));
-# endif
} else
- { /* Return the actual names used */
- if (!label.oprclass && !offset.oprclass)
- { /* Routine only (no label or offset) */
- rettrip = maketriple(op2);
- rettrip->operand[0] = put_str(rtn_str.addr, rtn_str.len);
- ref = newtriple(OC_PARAMETER);
- ref->operand[0] = put_str(labname.addr, labname.len);
- ref->operand[1] = put_ilit(0);
- rettrip->operand[1] = put_tref(ref);
- ins_triple(rettrip);
- return rettrip;
- } else
- routine = put_str(rtn_str.addr, rtn_str.len);
+ { /* Triples for indirect code (at indirect compile time) */
+ routine = put_str(rtnname.addr, rtnname.len);
+ if (!textname)
+ { /* If not returning text name, convert text name to routine header address */
+ ref = newtriple(OC_RHDADDR1);
+ ref->operand[0] = routine;
+ routine = put_tref(ref);
+ }
}
- } else
- { /* Triples for indirect code */
- routine = put_str(rtn_str.addr, rtn_str.len);
+ break;
+ case TK_ATSIGN:
+ if (!indirection(&routine))
+ return NULL;
if (!textname)
{ /* If not returning text name, convert text name to routine header address */
ref = newtriple(OC_RHDADDR1);
ref->operand[0] = routine;
routine = put_tref(ref);
}
- }
- break;
- case TK_ATSIGN:
- if (!indirection(&routine))
+ break;
+ default:
+ stx_error(ERR_RTNNAME);
return NULL;
- if (!textname)
- { /* If not returning text name, convert text name to routine header address */
- ref = newtriple(OC_RHDADDR1);
- ref->operand[0] = routine;
- routine = put_tref(ref);
- }
- break;
- default:
- stx_error(ERR_RTNNAME);
- return NULL;
}
} else
{
- if (!label.oprclass && (0 == labname.len))
+ if ((NO_REF == label.oprclass) && (0 == labname.len))
{
stx_error(ERR_LABELEXPECTED);
return NULL;
@@ -204,15 +212,18 @@ triple *entryref(opctype op1, opctype op2, mint commargcode, boolean_t can_comma
if (!textname)
routine = put_tref(newtriple(OC_CURRHD));
else
- { /* If we need a name, the mechanism to retrieve it differs between normal and indirect compilation */
- /* For normal compile, use routine name set when started compile */
- /* Routine name can vary. textname=TRUE callers (zgoto) fetch name from frame_pointer at runtime */
- routine = put_str("",0);
+ { /* If we need a name, the mechanism to retrieve it differs between normal and indirect compilation.
+ * For normal compile, use routine name set when started compile. Routine name can vary. For textname=TRUE
+ * callers (zgoto) fetch name from frame_pointer at runtime.
+ */
+ routine = put_str("", 0);
}
}
- if (!offset.oprclass)
+ if (NO_REF == offset.oprclass)
+ /* No offset supplied - supply default */
offset = put_ilit(0);
- if (!label.oprclass)
+ if (NO_REF == label.oprclass)
+ /* No label indirect - value resides in labname so make a proper parameter out of it */
label = put_str(labname.addr, labname.len);
ref = textname ? newtriple(OC_PARAMETER) : newtriple(OC_LABADDR);
ref->operand[0] = label;
@@ -226,3 +237,113 @@ triple *entryref(opctype op1, opctype op2, mint commargcode, boolean_t can_comma
next->operand[1] = put_tref(ref);
return rettrip;
}
+
+#ifdef USHBIN_SUPPORTED
+/* Routine used in a USHBIN build (UNIX Shared BInary) to generate the triples to reference (call, extrinsic or goto)
+ * an external routine. This version calls additional opcodes to dynamically autorelink routines if the routine has been
+ * changed since it was last linked if autorelinking is enabled. This requires that all such M-calls with a routine specified
+ * as part of the call (i.e. DO label^routine instead of just DO label) be invoked as external routines so this routine
+ * creates an external reference to the given routine/label. Note indirects do not come through here.
+ *
+ * Parameters:
+ *
+ * op1 - Opcode to use for local routine (only passed into this flavor for compatibility with the NON-USHBIN version
+ * that follows below. This routine does not use it.
+ * op2 - Opcode to use for external call.
+ * rtnname - Text name of routine being referenced.
+ * labname - Text label being referenced in given routine (may be NULL string)
+ *
+ * Note this routine sets up the complete reference (label and routine) so returning from entryref() is expected after calling
+ * this routine.
+ */
+STATICFNDEF triple *insert_extref_fast(opctype op1, opctype op2, mident *rtnname, mident *labname)
+{
+ triple *intermed1, *intermed2, *rettrip, *next, *ref;
+ mstr lbl_str;
+
+ intermed1 = maketriple(OC_RHD_EXT);
+ ref = intermed1;
+ ref->operand[0] = put_str(rtnname->addr, rtnname->len); /* arg 1 */
+ next = newtriple(OC_PARAMETER);
+ ref->operand[1] = put_tref(next);
+ ref = next;
+ ref->operand[0] = put_str(labname->addr, labname->len); /* arg 2 */
+ next = newtriple(OC_PARAMETER);
+ ref->operand[1] = put_tref(next);
+ ref = next;
+ ref->operand[0] = put_cdlt(rtnname); /* arg 3 */
+ next = newtriple(OC_PARAMETER);
+ ref->operand[1] = put_tref(next);
+ ref = next;
+ CONVERT_MUTIL_NAME_PERCENT_TO_UNDERSCORE(rtnname);
+ mlabel2xtern(&lbl_str, rtnname, labname);
+ ref->operand[0] = put_cdlt(&lbl_str); /* arg 4 */
+ ins_triple(intermed1);
+ /* op_rhd_ext needs to return two pointers: one to a rtn hdr, and one to
+ * a line number entry (label). op_rhd_ext directly returns the rtn hdr
+ * and sets lab_proxy, which op_lab_ext fetches and feeds into the opcode
+ * doing the reference (DO, extrinsics, and ZBREAK).
+ */
+ intermed2 = newtriple(OC_LAB_EXT); /* extracts, returns global variable */
+ rettrip = newtriple(op2);
+ rettrip->operand[0] = put_tref(intermed1);
+ rettrip->operand[1] = put_tref(intermed2);
+ return rettrip;
+}
+
+/* This routine is called to generate a triple for a given routine reference when the label is indirect and the routine
+ * isn't. Since an indirect is involved, this form generates individual triples for resolving the routine and label
+ * addresses with this routine generating only the routine resolution triples. Since this is for a USHBIN build, all
+ * references where a routine name is provided generate an external call type call so auto-relinking can occur if it
+ * is enabled.
+ */
+STATICFNDEF oprtype insert_extref(mident *rtnname)
+{ /* Generate routine reference triple */
+ INSERT_EXTREF_NOMORPH_AND_RETURN(rtnname);
+}
+
+#else
+/* Routine used in a NON_USHBIN build to generate triples for a label reference (call, function invocation or goto) a routine.
+ * At this point, it could be an internal or external routine. Note indirects do not come here.
+ *
+ * Parameters:
+ *
+ * same as described in the USHBIN version of this routine above except both op1 and op2 are used.
+ */
+STATICFNDEF triple *insert_extref_fast(opctype op1, opctype op2, mident *rtnname, mident *labname)
+{
+ triple *rettrip;
+ mstr lbl_str;
+
+ /* Do LABEL^RTN comes here (LABEL is *not* indirect) */
+ if (IS_SAME_RTN(rtnname, &routine_name))
+ { /* If same routine as current routine, we can morph the call into an internal call that merrily
+ * references only the label.
+ */
+ rettrip = newtriple(op1);
+ rettrip->operand[0] = put_mlab(labname);
+ } else
+ { /* Create an external reference to LABEL^RTN */
+ rettrip = maketriple(op2);
+ CONVERT_MUTIL_NAME_PERCENT_TO_UNDERSCORE(rtnname);
+ rettrip->operand[0] = put_cdlt(rtnname);
+ mlabel2xtern(&lbl_str, rtnname, labname);
+ rettrip->operand[1] = put_cdlt(&lbl_str);
+ ins_triple(rettrip);
+ }
+ return rettrip;
+}
+
+/* The NON_USHBIN flavor of thisroutine is similar to the USHBIN flavor except if the routine being called is the
+ * same as the current routine, we morph it into a local (same-routine) type call (no auto-relinking).
+ */
+STATICFNDEF oprtype insert_extref(mident *rtnname)
+{
+ if (!IS_SAME_RTN(rtnname, &routine_name))
+ { /* Generate external routine reference triple */
+ INSERT_EXTREF_NOMORPH_AND_RETURN(rtnname);
+ }
+ else /* Generate internal routine reference triple */
+ return put_tref(newtriple(OC_CURRHD));
+}
+#endif
diff --git a/sr_port/error.h b/sr_port/error.h
index 9bd9c9b..d107bdf 100644
--- a/sr_port/error.h
+++ b/sr_port/error.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -27,6 +27,9 @@ typedef struct err_ctl_struct
int msg_cnt;
} err_ctl;
+#ifdef UNIX
+#include "wbox_test_init.h" /* needed for DUMPABLE macro which uses WBTEST_ENABLED */
+#endif
#include "errorsp.h"
#define ERROR_RETURN error_return
@@ -45,6 +48,18 @@ typedef struct err_ctl_struct
/* to change default severity of msg to type */
#define MAKE_MSG_TYPE(msg, type) ((msg) & ~SEV_MSK | (type))
+/* Define SET_ERROR_CONDITION macro to set global variables "error_condition" as well as "severity" at the same time.
+ * If the two are not kept in sync, it is possible "severity" reflects INFO (from an older error) whereas
+ * "error_condition" is set to TPRETRY which means we would handle it as a TPRETRY INFO type error and that means the
+ * caller that issues rts_error of TPRETRY will see control being returned to it which goes into an out-of-design situation
+ * and could cause SIG-11 (GTM-8083).
+ */
+#define SET_ERROR_CONDITION(MSGID) \
+{ \
+ error_condition = MSGID; \
+ UNIX_ONLY(severity = (NULL == err_check(MSGID)) ? ERROR : SEVMASK(MSGID);) \
+}
+
/* Macro used intermittently to trace various error handling invocations */
/* #define DEBUG_ERRHND */
#ifdef DEBUG_ERRHND
diff --git a/sr_port/error_trap.h b/sr_port/error_trap.h
index 6f0e632..3271c1d 100644
--- a/sr_port/error_trap.h
+++ b/sr_port/error_trap.h
@@ -1,5 +1,5 @@
/****************************************************************
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,6 +13,7 @@
#define IS_ETRAP (err_act == &dollar_etrap.str)
#define ETRAP_IN_EFFECT (!ztrap_explicit_null && (0 == dollar_ztrap.str.len))
+#define NULLIFY_TRAP(TRAP) {TRAP.mvtype = MV_STR; TRAP.str.len = 0;}
#define DOLLAR_ECODE_MAXINDEX 32 /* maximum of 32 ecodes in $ECODE */
#define DOLLAR_STACK_MAXINDEX 256 /* maximum of 256 levels will be stored for $STACK(level) */
diff --git a/sr_port/exfunc.c b/sr_port/exfunc.c
index 1265e6e..520aa0d 100644
--- a/sr_port/exfunc.c
+++ b/sr_port/exfunc.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -58,7 +58,7 @@ int exfunc(oprtype *a, boolean_t alias_target)
{
if (OC_CDLIT == calltrip_opr1_tref->opcode)
assert(CDLT_REF == calltrip_opr1_tref->operand[0].oprclass);
- else
+ else USHBIN_ONLY(if (OC_LAB_EXT != calltrip_opr1_tref->opcode))
{
assert(OC_LABADDR == calltrip_opr1_tref->opcode);
assert(TRIP_REF == calltrip_opr1_tref->operand[1].oprclass);
diff --git a/sr_port/expritem.c b/sr_port/expritem.c
index cc36267..1b2588e 100644
--- a/sr_port/expritem.c
+++ b/sr_port/expritem.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -275,7 +275,9 @@ LITDEF nametabent fun_names[] =
,{7, "ZSEARCH"}
,{7, "ZSETPRV"}
,{8, "ZSIGPROC"}
+ ,{7, "ZSOCKET"}
,{4, "ZSUB"}, {7, "ZSUBSTR"}
+ ,{7, "ZSYSLOG"}
,{3, "ZTR"}, {8, "ZTRANSLA*"}
,{4, "ZTRI"}, {8, "ZTRIGGER"}
,{7, "ZTRNLNM"}
@@ -288,7 +290,7 @@ LITDEF unsigned char fun_index[27] =
{
0, 2, 2, 4, 6, 8, 12, 14, 14, /* a b c d e f g h i */
17, 19, 19, 21, 21, 25, 27, 29, 35, /* j k l m n o p q r */
- 39, 43, 47, 47, 48, 48, 48, 48, 116 /* s t u v w x y z ~ */
+ 39, 43, 47, 47, 48, 48, 48, 48, 118 /* s t u v w x y z ~ */
};
/* Each entry corresponds to an entry in fun_names */
@@ -331,11 +333,7 @@ LITDEF fun_data_type fun_data[] =
,{ OC_FNZBITSET, ALL_SYS }
,{ OC_FNZBITSTR, ALL_SYS }
,{ OC_FNZBITXOR, ALL_SYS }
-# ifdef __sun
- ,{ OC_FNZCALL,UNIX_OS}, { OC_FNZCALL,UNIX_OS}
-# else
,{ OC_FNZCALL, VMS_OS }, { OC_FNZCALL, VMS_OS }
-# endif
,{ OC_FNZCHAR, ALL_SYS }, { OC_FNZCHAR, ALL_SYS }
,{ OC_FNZCONVERT2, UNIX_OS }, { OC_FNZCONVERT2, UNIX_OS }
,{ OC_FNZDATE, ALL_SYS }
@@ -364,7 +362,9 @@ LITDEF fun_data_type fun_data[] =
,{ OC_FNZSEA, ALL_SYS }
,{ OC_FNZSETPRV, VMS_OS }
,{ OC_FNZSIGPROC, ALL_SYS }
+ ,{ OC_FNZSOCKET, ALL_SYS }
,{ OC_FNZSUBSTR, ALL_SYS }, { OC_FNZSUBSTR, ALL_SYS }
+ ,{ OC_FNZSYSLOG, UNIX_OS }
,{ OC_FNZTRANSLATE, ALL_SYS }, { OC_FNZTRANSLATE, ALL_SYS }
,{ OC_FNZTRIGGER, TRIGGER_OS }, { OC_FNZTRIGGER, TRIGGER_OS }
,{ OC_FNZTRNLNM, ALL_SYS }
@@ -441,7 +441,9 @@ GBLDEF int (*fun_parse[])(oprtype *, opctype) = /* contains addresses so can't
f_zsearch,
f_mstr,
f_zsigproc,
+ f_zsocket,
f_extract, f_extract, /* $ZSUBSTR */
+ f_one_mval, /* $ZSYSLOG */
f_translate, f_translate,
f_ztrigger, f_ztrigger,
f_ztrnlnm,
diff --git a/sr_port/ext2jnl.c b/sr_port/ext2jnl.c
index 7383b42..e937dab 100644
--- a/sr_port/ext2jnl.c
+++ b/sr_port/ext2jnl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,10 @@
#include "mdef.h"
#include <stddef.h> /* for offsetof() macro */
+#ifdef VMS
+#include <descrip.h> /* required for gtmsource.h */
+#endif
+
#include "gtm_ctype.h"
#include "mlkdef.h"
@@ -29,39 +33,85 @@
#include "zshow.h"
#include "mvalconv.h"
#include "str2gvkey.h"
+#include "repl_filter.h"
+#include "repl_msg.h"
+#include "gtmsource.h"
+#include "gdsblk.h"
GBLREF char *ext_stop;
GBLREF gv_key *gv_currkey;
+GBLREF boolean_t is_src_server;
+GBLREF repl_msg_ptr_t gtmsource_msgp;
+GBLREF int gtmsource_msgbufsiz;
+
static boolean_t in_tp;
static int4 num_records;
/* callers please set up the proper condition-handlers */
/* expects a null-terminated ext_buff. does the equivalent but inverse of jnl2ext */
-char *ext2jnlcvt(char *ext_buff, int4 ext_len, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved_strm_seqno)
+unsigned char *ext2jnlcvt(char *ext_buff, int4 ext_len, unsigned char **tr, int *tr_bufsiz,
+ seq_num saved_jnl_seqno, seq_num saved_strm_seqno)
{
char *ext_next;
- jnl_record *temp_rec;
+ unsigned char *rec, *rectop, *tmp, *origbuf, *temp_rec;
+ int tmpbufsiz, tmpsize;
+ rec = *tr;
+ rectop = rec + *tr_bufsiz;
temp_rec = rec;
for ( ; (NULL != (ext_next = strchr(ext_buff, '\n'))); )
{
*ext_next++ = '\0';
- rec = (jnl_record *)ext2jnl(ext_buff, rec, saved_jnl_seqno, saved_strm_seqno);
+ if (MAX_JNL_REC_SIZE > (rectop - rec))
+ { /* Remaining space not enough to hold ONE max-sized jnl record. Expand linearly */
+ tmpsize = *tr_bufsiz;
+ tmpbufsiz = tmpsize + (EXT2JNLCVT_EXPAND_FACTOR * MAX_JNL_REC_SIZE);
+ origbuf = *tr;
+ tmpsize = rec - origbuf;
+ if (is_src_server)
+ { /* In the case of the source server, the pointer "tr" passed in is actually
+ * 8 bytes after gtmsource_msgp and so the malloc/realloc needs to happen
+ * 8 bytes before. Also compression buffers need to be reallocated so hardcode
+ * all of this even though it is violation of information hiding in this generic
+ * routine. The alternative is to return an out-of-space status and bubble it up
+ * through all the callers until the caller of "repl_filter" and do the reallocation
+ * there and reinvoke through the same caller graph to come back here and resume
+ * operation. That is tricky and not considered worth the effort since there are only
+ * two callers of this function (one through source server and one through the receiver
+ * server). Hence this choice.
+ */
+ assert((unsigned char *)>msource_msgp->msg[0] == *tr);
+ assert(*tr_bufsiz == gtmsource_msgbufsiz);
+ UNIX_ONLY(gtmsource_alloc_msgbuff(tmpbufsiz, FALSE);)
+ VMS_ONLY(gtmsource_alloc_msgbuff(tmpbufsiz);)
+ *tr_bufsiz = gtmsource_msgbufsiz;
+ *tr = >msource_msgp->msg[0];
+ rec = *tr + tmpsize;
+ rectop = (unsigned char *)gtmsource_msgp + gtmsource_msgbufsiz;
+ } else
+ {
+ tmp = malloc(tmpbufsiz);
+ memcpy(tmp, origbuf, tmpsize);
+ free(origbuf);
+ *tr = tmp;
+ *tr_bufsiz = tmpbufsiz;
+ rec = tmp + tmpsize;
+ rectop = tmp + tmpbufsiz;
+ }
+ }
+ rec = (unsigned char *)ext2jnl(ext_buff, (jnl_record *)rec, saved_jnl_seqno, saved_strm_seqno);
assert(0 == (INTPTR_T)rec % JNL_REC_START_BNDRY);
if (ext_stop == ext_buff)
break;
ext_buff = ext_next;
}
-
- assert(rec != temp_rec);
+ assertpro(rec != temp_rec);
ext_stop = ext_buff;
- return (char *)rec;
+ return rec;
}
-
-/* expects a single null-terminated ptr (equivalent to one line in the extract-file) */
-
+/* expects a single null-terminated ptr (equivalent to one line in the journal extract file) */
char *ext2jnl(char *ptr, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved_strm_seqno)
{
unsigned char *pool_save, ch, chtmp;
@@ -122,26 +172,28 @@ char *ext2jnl(char *ptr, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved
# ifdef GTM_TRIGGER
case MUEXT_ZTWORM:
- if (in_tp)
- {
- if (0 == num_records)
- rec->prefix.jrec_type = JRT_TZTWORM;
- else
- rec->prefix.jrec_type = JRT_UZTWORM;
- num_records++;
- } else
- GTMASSERT; /* ZTWORMHOLE should always been seen only inside a TP fence */
+ assertpro(in_tp);
+ if (0 == num_records)
+ rec->prefix.jrec_type = JRT_TZTWORM;
+ else
+ rec->prefix.jrec_type = JRT_UZTWORM;
+ num_records++;
+ break;
+ case MUEXT_LGTRIG:
+ assertpro(in_tp);
+ if (0 == num_records)
+ rec->prefix.jrec_type = JRT_TLGTRIG;
+ else
+ rec->prefix.jrec_type = JRT_ULGTRIG;
+ num_records++;
break;
case MUEXT_ZTRIG:
- if (in_tp)
- {
- if (0 == num_records)
- rec->prefix.jrec_type = JRT_TZTRIG;
- else
- rec->prefix.jrec_type = JRT_UZTRIG;
- num_records++;
- } else
- GTMASSERT; /* ZTRIGGER should always been seen only inside a TP fence */
+ assertpro(in_tp);
+ if (0 == num_records)
+ rec->prefix.jrec_type = JRT_TZTRIG;
+ else
+ rec->prefix.jrec_type = JRT_UZTRIG;
+ num_records++;
break;
# endif
@@ -221,12 +273,12 @@ char *ext2jnl(char *ptr, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved
rec->jrec_tcom.suffix.suffix_code = JNL_REC_SUFFIX_CODE;
return ((char_ptr_t)rec) + TCOM_RECLEN;
}
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype));
ptr = strtok(NULL, "\\"); /* get the update_num field */
assert(NULL != ptr);
assert(OFFSETOF(struct_jrec_upd, update_num) == OFFSETOF(struct_jrec_ztworm, update_num));
rec->jrec_set_kill.update_num = num_records;
- if (MUEXT_ZTWORM != exttype)
+ if ((MUEXT_ZTWORM != exttype) && (MUEXT_LGTRIG != exttype))
{
ptr = strtok(NULL, "\\"); /* get the nodeflags field */
assert(NULL != ptr);
@@ -234,7 +286,7 @@ char *ext2jnl(char *ptr, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved
}
ptr += (strlen(ptr) + 1); /* get the key-value and data also; can't use strtok since there might be '\\' in the subscript */
assert(NULL != ptr);
- if (MUEXT_ZTWORM != exttype)
+ if ((MUEXT_ZTWORM != exttype) && (MUEXT_LGTRIG != exttype))
{
assert(IS_SET_KILL_ZKILL_ZTRIG(rectype));
len = STRLEN(ptr);
@@ -260,10 +312,11 @@ char *ext2jnl(char *ptr, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved
src.len = val_len;
src.addr = val_off;
} else
- { /* ZTWORMHOLE */
- assert(IS_ZTWORM(rectype));
+ { /* ZTWORMHOLE or LGTRIG jnl record */
+ assert(IS_ZTWORM(rectype) || IS_LGTRIG(rectype));
src.addr = ptr;
src.len = STRLEN(ptr);
+ assert(FIXED_ZTWORM_RECLEN == FIXED_LGTRIG_RECLEN);
temp_reclen = (int)(FIXED_ZTWORM_RECLEN);
}
des.len = 0;
diff --git a/sr_port/f_zsearch.c b/sr_port/f_zsearch.c
index a09e276..2c42601 100644
--- a/sr_port/f_zsearch.c
+++ b/sr_port/f_zsearch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -17,21 +17,24 @@
int f_zsearch(oprtype *a, opctype op)
{
- triple *r;
+ triple *r, *rop;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
r = maketriple(op);
if (EXPR_FAIL == expr(&(r->operand[0]), MUMPS_STR))
return FALSE;
+ rop = newtriple(OC_PARAMETER);
+ r->operand[1] = put_tref(rop);
if (TK_COMMA != TREF(window_token))
- r->operand[1] = put_ilit(0);
+ rop->operand[0] = put_ilit(0);
else
{
advancewindow();
- if (EXPR_FAIL == expr(&(r->operand[1]), MUMPS_INT))
+ if (EXPR_FAIL == expr(&(rop->operand[0]), MUMPS_INT))
return FALSE;
}
+ rop->operand[1] = put_ilit(1); /* This is an M-function call */
ins_triple(r);
*a = put_tref(r);
return TRUE;
diff --git a/sr_port/f_zsocket.c b/sr_port/f_zsocket.c
new file mode 100644
index 0000000..502d231
--- /dev/null
+++ b/sr_port/f_zsocket.c
@@ -0,0 +1,85 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+#include "compiler.h"
+#include "opcode.h"
+#include "toktyp.h"
+#include "advancewindow.h"
+
+error_def(ERR_MAXARGCNT);
+
+#define MAX_ZSOCKET_ARGS 6 /* argc, dst, device, keyword, arg1, arg2 */
+
+int f_zsocket(oprtype *a, opctype op)
+{
+ int argc;
+ char tok_temp;
+ oprtype *argp, argv[MAX_ZSOCKET_ARGS];
+ triple *curr, *last, *root;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ argp = &argv[0];
+ argc = 0;
+ if (TK_COMMA == TREF(window_token))
+ { /* empty first argument is for socket stringpool */
+ curr = newtriple(OC_NULLEXP);
+ *argp = put_tref(curr);
+ } else
+ {
+ if (EXPR_FAIL == expr(argp, MUMPS_STR)) /* device name */
+ return FALSE;
+ }
+ assert(TRIP_REF == argp->oprclass);
+ argc++;
+ argp++;
+ advancewindow();
+ if (EXPR_FAIL == expr(argp, MUMPS_STR)) /* which item */
+ return FALSE;
+ assert(TRIP_REF == argp->oprclass);
+ argc++;
+ argp++;
+ for (;;)
+ {
+ if (TK_COMMA != TREF(window_token))
+ break;
+ advancewindow();
+ tok_temp = TREF(window_token);
+ if ((2 == argc) && ((TK_COMMA == tok_temp) || (TK_RPAREN == tok_temp)))
+ { /* missing third argument is for default index */
+ curr = newtriple(OC_NULLEXP);
+ *argp = put_tref(curr);
+ } else if (EXPR_FAIL == expr(argp, MUMPS_EXPR))
+ return FALSE;
+ assert(TRIP_REF == argp->oprclass);
+ argc++;
+ argp++;
+ if (MAX_ZSOCKET_ARGS < argc)
+ {
+ stx_error(ERR_MAXARGCNT, 1, MAX_ZSOCKET_ARGS);
+ return FALSE;
+ }
+ }
+ root = last = maketriple(op);
+ root->operand[0] = put_ilit(argc + 1);
+ argp = &argv[0];
+ for (; argc > 0 ;argc--, argp++)
+ {
+ curr = newtriple(OC_PARAMETER);
+ curr->operand[0] = *argp;
+ last->operand[1] = put_tref(curr);
+ last = curr;
+ }
+ ins_triple(root);
+ *a = put_tref(root);
+ return TRUE;
+}
diff --git a/sr_port/fao_parm.h b/sr_port/fao_parm.h
index 9544227..624bb16 100644
--- a/sr_port/fao_parm.h
+++ b/sr_port/fao_parm.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,12 +9,25 @@
* *
****************************************************************/
-typedef struct {
-unsigned short len;
-unsigned char fill1;
-unsigned char fill2;
-char *addr;
-}desc_struct;
+typedef struct
+{
+ unsigned short len;
+ unsigned char fill1;
+ unsigned char fill2;
+ char *addr;
+} desc_struct;
+/* Currently, the maximum number of argument placeholders in a message is 16. Certain types of placeholders (such as !AD) require
+ * two arguments, length and address, to be passed to the corresponding output function (normally, rts_error, send_msg, or putmsg).
+ * We are being safe and taking the maximum number of placeholders as 17, doubling the number for length-address types.
+ */
+#define MAX_FAO_PARMS 34
-#define MAX_FAO_PARMS 20
+/* Since @... type parameters involve 8-byte values, we need an additional slot per each such value on 32-bit platforms, define the
+ * number of INTPTR_T-typed slots appropriately for both 64- and 32-bit architectures.
+ */
+#ifdef GTM64
+# define NUM_OF_FAO_SLOTS MAX_FAO_PARMS
+#else
+# define NUM_OF_FAO_SLOTS ((MAX_FAO_PARMS + 1) / 2 * 3)
+#endif
diff --git a/sr_port/fntext_ch.c b/sr_port/fntext_ch.c
index 37ce64c..7fe49cf 100644
--- a/sr_port/fntext_ch.c
+++ b/sr_port/fntext_ch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,7 @@
#include "mdef.h"
#include "error.h"
+#include "op.h" /* for OP_TROLLBACK */
error_def(ERR_ASSERT);
error_def(ERR_GTMASSERT);
@@ -23,12 +24,30 @@ error_def(ERR_STACKOFLOW);
error_def(ERR_TPRETRY);
error_def(ERR_VMSMEMORY);
+GBLREF uint4 dollar_tlevel;
+
CONDITION_HANDLER(fntext_ch)
{
+ int tlevel;
+
START_CH(TRUE);
- GTMTRIG_ONLY(TREF(in_op_fntext) = FALSE);
+# ifdef GTM_TRIGGER
+ tlevel = TREF(op_fntext_tlevel);
+ TREF(op_fntext_tlevel) = 0;
+# endif
if (!DUMPABLE && (SIGNAL != ERR_TPRETRY))
{
+# ifdef GTM_TRIGGER
+ if (tlevel)
+ { /* $TEXT was done on a trigger routine. Check if $tlevel is different from ESTABLISH time to UNWIND time */
+ tlevel--; /* get real tlevel */
+ if (tlevel != dollar_tlevel)
+ {
+ assert(tlevel < dollar_tlevel);
+ OP_TROLLBACK(tlevel - dollar_tlevel);
+ }
+ }
+# endif
UNWIND(NULL, NULL); /* As per the standard, $TEXT returns null string if there are errors while */
/* loading/linking with the entryref. So, we ignore non-fatal errors. */
} else
diff --git a/sr_port/format_targ_key.c b/sr_port/format_targ_key.c
index 5dbf51f..3be5050 100644
--- a/sr_port/format_targ_key.c
+++ b/sr_port/format_targ_key.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -25,6 +25,7 @@ unsigned char *format_targ_key(unsigned char *out_char_ptr, int4 max_size, gv_ke
{
unsigned char ch, *gvkey_char_ptr, *out_top, *work_char_ptr, work_buff[MAX_ZWR_KEY_SZ], *work_top;
boolean_t is_string;
+ mstr opstr;
DEBUG_ONLY(unsigned char *gvkey_top_ptr;)
assert(12 < max_size);
@@ -62,7 +63,9 @@ unsigned char *format_targ_key(unsigned char *out_char_ptr, int4 max_size, gv_ke
is_string = TRUE;
*out_char_ptr++ = '"';
}
- work_top = gvsub2str(gvkey_char_ptr, work_buff, dollarc);
+ opstr.addr = (char *)work_buff;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ work_top = gvsub2str(gvkey_char_ptr, &opstr, dollarc);
if (!is_string)
{
for (work_char_ptr = work_buff; work_char_ptr < work_top;)
diff --git a/sr_port/fullbool.h b/sr_port/fullbool.h
index dd0053f..64c77ac 100644
--- a/sr_port/fullbool.h
+++ b/sr_port/fullbool.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2012 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,16 +13,16 @@
enum gtm_bool_type
{
- GTM_BOOL = 0,
- FULL_BOOL,
- FULL_BOOL_WARN
+ GTM_BOOL = 0, /* original GT.M short-circuit Boolean evaluation with naked maintenance */
+ FULL_BOOL, /* standard behavior - evaluate everything with a side effect */
+ FULL_BOOL_WARN /* like FULL_BOOL but give compiler warnings when it makes a difference */
};
enum gtm_se_type
{
- OLD_SE = 0,
- STD_SE,
- SE_WARN
+ OLD_SE = 0, /* ignore side effect implications */
+ STD_SE, /* reorder argument processing for left-to-right side effects */
+ SE_WARN /* like STD but give compiler warnings when it makes a difference */
};
#endif /* FULLBOOL_H_INCLUDED */
diff --git a/sr_port/gbldefs.c b/sr_port/gbldefs.c
index 6396654..76402e9 100644
--- a/sr_port/gbldefs.c
+++ b/sr_port/gbldefs.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -131,6 +131,7 @@
# include "gtmcrypt.h"
# include "gdsblk.h"
# include "muextr.h"
+# include "gtmxc_types.h"
# endif
#ifdef GTM_TLS
#include "gtm_tls_interface.h"
@@ -926,10 +927,13 @@ GBLDEF char *gtm_utf8_locale_object;
GBLDEF boolean_t gtm_tag_utf8_as_ascii = TRUE;
#endif
#ifdef GTM_CRYPT
-LITDEF char gtmcrypt_repeat_msg[] = "Please look at prior messages related to encryption for more details";
-GBLDEF boolean_t gtmcrypt_initialized; /* Set to TRUE if gtmcrypt_init() completes successfully */
-GBLDEF char dl_err[MAX_ERRSTR_LEN];
-GBLDEF mstr pvt_crypt_buf; /* Temporary buffer needed where in-place encryption/decryption is not an option */
+LITDEF char gtmcrypt_repeat_msg[] = "Please look at prior messages related to encryption for more details";
+GBLDEF char *gtmcrypt_badhash_size_msg;
+GBLDEF boolean_t gtmcrypt_initialized; /* Set to TRUE if gtmcrypt_init() completes successfully */
+GBLDEF char dl_err[MAX_ERRSTR_LEN];
+GBLDEF mstr pvt_crypt_buf; /* Temporary buffer needed where in-place encryption/decryption is not an option */
+LITDEF gtm_string_t null_iv = {0, ""};
+GBLDEF boolean_t err_same_as_out;
#endif /* GTM_CRYPT */
#ifdef DEBUG
/* Following definitions are related to white_box testing */
@@ -1074,7 +1078,9 @@ GBLDEF is_anticipatory_freeze_needed_t is_anticipatory_freeze_needed_fnptr;
GBLDEF set_anticipatory_freeze_t set_anticipatory_freeze_fnptr;
GBLDEF boolean_t is_jnlpool_creator;
GBLDEF char gtm_dist[GTM_PATH_MAX]; /* Value of $gtm_dist env variable */
+GBLDEF boolean_t gtm_dist_ok_to_use = FALSE; /* Whether or not we can use $gtm_dist */
GBLDEF semid_queue_elem *keep_semids; /* Access semaphores that should be kept because shared memory is up */
+GBLDEF boolean_t dmterm_default; /* Retain default line terminators in the direct mode */
#endif
GBLDEF boolean_t in_jnl_file_autoswitch; /* Set to TRUE for a short window inside jnl_file_extend when we are about
* to autoswitch; used by jnl_write. */
@@ -1107,3 +1113,5 @@ GBLDEF gtm_tls_ctx_t *tls_ctx; /* Process private pointer to SSL/TLS context.
* Socket devices.
*/
#endif
+
+GBLDEF lv_val *active_lv;
diff --git a/sr_port/gde.hlp b/sr_port/gde.hlp
index 0ba49e9..a9a7eb5 100644
--- a/sr_port/gde.hlp
+++ b/sr_port/gde.hlp
@@ -3,49 +3,61 @@
The GT.M Global Directory Editor (GDE) is a utility for creating,
examining, and modifying a global directory. GDE is a program written in M
- and you can invoke it from the shell with $gtm_dist/mumps -run ^GDE, with
- the gtm alias gtm -run GDE, or from inside the direct mode with Do ^GDE.
+ and you can invoke it from the shell with $gtm_dist/mumps -run ^GDE.
- **Note**
+ Because GDE is an M program, you can also invoke GDE from a GT.M process
+ with DO ^GDE. If you invoke GDE with a DO and modify the map of global
+ directly currently opened by that process, you must HALT and restart the
+ process for the process to pick up the revised mapping. FIS expects users
+ normally run GDE from the shell --$gtm_dist/mumps -run GDE.
+
+ The input to GDE can be a command file. In a production environment, FIS
+ recommends using command files to define database configurations and
+ putting them under version control.
+
+ **Caution**
- The input to GDE can be a text file. In a production environment, FIS
- recommends using text files to define database configurations, and putting
- these text files under version control.
-
- A global directory stores database attributes and mapping rules. The
- mapping rules are like a sieve for globals that determines which database
- files hold which global names. The database attributes serve as a
- blueprint that MUPIP CREATE uses to create new database file(s). Once a
- database file is created, GT.M continues to use the global directory as a
- sieve. However, once MUPIP CREATE applies the database attributes
- (blueprint) to create a database file, GT.M does not use the blueprint
- until the next MUPIP CREATE. Therefore, if you use MUPIP SET (or DSE) to
- change the attributes of a database file, always perform an equivalent
- change to any global directory used for a subsequent MUPIP CREATE.
+ A global directory stores database attributes and mapping rules. Processes
+ use mapping rules to determine which database file contains a global
+ variable node. MUPIP CREATE uses database attributes to create new
+ database file(s). Once MUPIP CREATE applies the database attributes to
+ create a database file, GT.M does not use the attributes until the next
+ MUPIP CREATE. If you use MUPIP SET (or DSE) to change the attributes of a
+ database file, always perform an equivalent change to any global directory
+ used for a subsequent MUPIP CREATE. Conversely, if you change attributes
+ with GDE, existing database files must be explicitly changed with MUPIP
+ SET or DSE.
2 Identifying_the_Current_Global_Directory
Identifying the Current Global Directory
- GT.M identifies the current Global Directory by referring to the
- environment variable gtmgbldir. GDE, MUPIP, LKE, DSE, and the GT.M
- run-time system use this environment variable. The run-time system
- normally uses this environment variable, but may also access a Global
- Directory by setting $ZGBLDIR or by using the extended global reference ||
- or {} syntax.
+ At process startup, the environment variable gtmgbldir identifies the
+ global directory to the process. M application code can access and change
+ the global directory through the $ZGBLDIR intrinsic special variable,
+ which is initialized from $gtmgbldir at process startup. M application
+ code can also use extended global references with the || or {} syntax.
- If you maintain multiple Global Directories, define gtmgbldir to point to
- the currently active Global Directory. You may want to define gtmgbldir in
- your login file. Note that this definition is a pathname. If it does not
- start with a "/", then it is a relative pathname and GT.M searches for it
- starting in the current working directory.
+ Note that $gtmgbldir / $ZGBLDIR are pathnames. If they do not start with a
+ "/", then the pathname is relative and GT.M searches for the global
+ directory starting in the current working directory.
- To change the current Global Directory assignment, specify a new
- definition for gtmgbldir.
+ To change the Global Directory used by processes, specify a new value for
+ gtmgbldir.
Example:
- $ gtmgbldir=prod.gld
- $ export gtmgbldir
+ $ export gtmgbldir=/home/jdoe/node1/prod.gld
+
+ When you invoke GDE and no Global Directory exists for gtmgbldir, GDE
+ creates a minimal default Global Directory that is a starting point or
+ template for building global directories for your specific needs.
+
+ To retain the default Global Directory, exit GDE without making any
+ changes.
+
+ Example:
+
+ $ export gtmgbldir=/home/jdoe/node1/prod.gld
2 Creating_a_Default_Global_Directory
Creating a Default Global Directory
@@ -57,15 +69,15 @@
Directory also serves as a starting point or template for building custom
global directories.
- To retain this default Global Directory, exit GDE without making any
+ To retain the default Global Directory, quit GDE without making any
changes.
Example:
- $ gtmgbldir=./mumps.gld
+ $ gtmgbldir=/usr/accntg/jones/mumps.gld
$ export gtmgbldir
- $ gtm
- GTM>d ^GDE
+ $ $gtm_dist/mumps -dir
+ GTM>do ^GDE
%GDE-I-GDUSEDEFS, Using defaults for Global Directory
/usr/accntg/jones/mumps.gld
GDE> EXIT
@@ -76,8 +88,8 @@
2 Mapping_Global_Variables_in_a_Global_Directory
Mapping Global Variables in a Global Directory
- Mapping is the process of connecting a global variable name to a database
- file.
+ Mapping is the process of connecting a global variable name or a subtree
+ or a subscript range to a database file.
A complete mapping has the following four components:
@@ -106,25 +118,29 @@
subsequent changes to these characteristics in the Global Directory have
no effect on an existing database.
- When you create a new mapping, GDE ensures that it has all these
- components by refusing to complete the EXIT command until all components
- of the mapping exist. Informational messages inform you of any missing or
- extra components.
+ On EXIT, GDE validates the global directory to ensure that every legal
+ global variable node maps to exactly one region; that every region has at
+ least one global variable node mapping to it and that it maps to exactly
+ one segment; that every segment has exactly one region mapping to it; and
+ that the attributes for each region and segment are internally consistent.
+ GDE will not create a structurally unsound global directory, and will not
+ exit until it validates the global directory. Informational messages
+ advise you of structural inconsistencies.
2 Examining_the_Default_Global_Directory
Examining the Default Global Directory
- The default Global Directory looks like this:
+ A Global Directory looks like this:
- *** TEMPLATES ***
+ *** TEMPLATES ***
Std Inst
Def Rec Key Null Null Freeze Qdb
Region Coll Size Size Subs Coll Jnl on Error Rndwn
----------------------------------------------------------------------------------------------------
<default> 0 4080 255 NEVER Y Y DISABLED DISABLED
- Jnl File (def ext: .mjl) Before Buff Alloc Exten AutoSwitch
- --------------------------------------------------------------------------------------
- <default> <based on DB file-spec> Y 2308 2048 2048 8386560
+ Jnl File (def ext: .mjl) Before Buff Alloc Exten AutoSwitch
+ ------------------------------------------------------------------------------------------
+ <default> <based on DB file-spec> Y 2308 2048 2048 8386560
Segment Active Acc Typ Block Alloc Exten Options
------------------------------------------------------------------------------
@@ -132,8 +148,10 @@
LOCK = 40
RES = 0
ENCR = OFF
+ MSLT =1024
<default> MM DYN 4096 5000 10000 DEFER
LOCK = 40
+ MSLT =1024
*** NAMES ***
Global Region
@@ -141,11 +159,11 @@
* DEFAULT
*** REGIONS ***
- Std Inst
- Dynamic Def Rec Key Null Null Freeze Qdb
- Region Segment Coll Size Size Subs Coll Jnl on Error Rndwn
- -----------------------------------------------------------------------------------------------------------------
- DEFAULT DEFAULT 0 4080 255 NEVER Y Y DISABLED DISABLED
+ Std Inst
+ Dynamic Def Rec Key Null Null Freeze Qdb
+ Region Segment Coll Size Size Subs Coll Jnl on Error Rndwn
+ --------------------------------------------------------------------------------------------------------------------------
+ DEFAULT DEFAULT 0 4080 255 NEVER Y Y DISABLED DISABLED
*** JOURNALING INFORMATION ***
Region Jnl File (def ext: .mjl) Before Buff Alloc Exten AutoSwitch
@@ -161,18 +179,18 @@
LOCK= 40
RES = 0
ENCR=OFF
+ MSLT=1024
*** MAP ***
- - - - - - - - - - Names - - - - - - - - - -
From Up to Region / Segment / File(def ext: .dat)
- --------------------------------------------------------------------------------------------------------
+ --------------------------------------------------------------------------------------------------------------------------
% ... REG = DEFAULT
SEG = DEFAULT
FILE = $gtmdir/$gtmver/g/gtm.dat
LOCAL LOCKS REG = DEFAULT
SEG = DEFAULT
FILE = $gtmdir/$gtmver/g/gtm.dat
- GDE>
There are five primary sections in a Global Directory:
@@ -198,15 +216,16 @@
NAMES
- An M program sees a monolithic global variable name space. The NAMES
- section of the Global Directory partitions the name space so that
- different globals reside in different files. While each M global can
- reside in only one file, each file can store many M globals.
+ An M program sees a monolithic global variable namespace. The NAMES
+ section of the Global Directory partitions the namespace so that a global
+ name or a global name with a subscript range reside in different database
+ files. An M global can reside in one more database file, each database
+ file can store many M globals.
REGIONS
The REGIONS section lists all of the regions in the Global Directory. Each
- region defines common properties for all the M global variables;
+ region defines common properties for a set of M global variables or nodes;
therefore, multiple sets of names from the NAMES section map onto a single
region.
@@ -230,12 +249,12 @@
This section of the Global Directory lists the current mapping of names to
region to segment to file. In the default Global Directory, there are two
lines in this section: one specifies the destination for all globals, the
- other one is for local locks. If you add any new mapping component
- definitions (that is, any new names, regions, or segments), this section
- displays the current status of that mapping. Any components of the mapping
- not currently defined display "NONE". Because GDE requires all elements of
- a mapping to be defined, you will not be able to EXIT (and save) your
- Global Directory until you complete all mappings.
+ other one is for M LOCK resources with local variable names. If you add
+ any new mapping component definitions (that is, any new names, regions, or
+ segments), this section displays the current status of that mapping. Any
+ components of the mapping not currently defined display "NONE". Because
+ GDE requires all elements of a mapping to be defined, you will not be able
+ to EXIT (and save) your Global Directory until you complete all mappings.
2 Global_Directory_Abbreviations
Global Directory Abbreviations
@@ -259,6 +278,7 @@
JNL JOURNAL
KeySize KEY_SIZE
LOCK LOCK_SPACE
+ MSLT MUTEX_SLOTS
Null Subs NULL_SUBSCRIPTS
Qdb Rndwn QDBRUNDOWN
Std Null Coll STDNULLCOLL
@@ -270,14 +290,14 @@
2 Customizing_a_Global_Directory
Customizing a Global Directory
- Once you have installed GT.M and verified its operation, create a Global
- Directory based on your needs. To create this customized Global Directory,
- use the appropriate GDE commands and qualifiers to build the desired
+ Once you have installed GT.M and verified its operation, create Global
+ Directories based on your needs. To create customized Global Directories,
+ use the appropriate GDE commands and qualifiers to build each desired
Global Directory. The GDE commands are described later in this chapter.
You can also create a text file of GDE commands with a standard text
editor and process this file with GDE. In a production environment, this
- gives better configuration control than interactive usage with GDE.
+ gives better configuration management than interactive usage with GDE.
3 Adding_a_Journaling_Information_Section
Adding a Journaling Information Section
@@ -322,12 +342,12 @@
To leave GDE:
- 1. Use the GDE EXIT command to save all changes and return to the shell.
+ 1. Use the GDE EXIT command to save all changes and return to the caller.
GDE> EXIT
2. Use the GDE QUIT command to discard all changes and return to the
- shell. This will not save any changes.
+ caller. This will not save any changes.
GDE> QUIT
@@ -337,30 +357,39 @@
This section lists the parameters that apply to defining each component of
a mapping.
- NAME
+ NAMES
- The name is the portion of the global variable name without subscripts.
- More than one name can map to a single region, but a single name can only
- map to one region.
+ The NAMES section contains mappings of M global name spaces. More than one
+ name space can map to a single region but a single name space can only map
+ to one region.
- A name:
+ A name space:
- o Maps to only one region in the Global Directory.
o Is case sensitive.
o Must begin with an alphabetic character or a percent sign (%).
- o Can be one to 31 alphanumeric characters.
o Can be a discrete "global" name, for example, aaa corresponds to the
global variable ^aaa.
- o Can be a partial name ending with a wild card ("*"), for example, abc*
- represents all globals beginning with the letters ^abc.
+ o Can be a global name ending with a wild card ("*"), for example, abc*
+ represents the set of global nodes which have abc as the starting
+ prefix.
+ o Can be a subtree of a global name, for example, abc(1) represents a
+ subtree of the global ^abc.
+ o Can be a subscript range, for example, abc(1:10) represents all nodes
+ starting from ^abc(1) up to (but not including) to ^abc(10).
+ o A global name can be one to 31 alphanumeric characters. However, the
+ combined length of a global and its subscripts is limited to 1,019
+ bytes (the maximum key size supported by GT.M). Note that the byte
+ length of the subscripted global specification can exceed the maximum
+ KeySize specified for its region.
+ o Maps to only one region in the Global Directory.
- REGION
+ REGIONS
- A region is a logical structure that holds information about a portion of
- a database, such as key-size and record-size. A key is the internal
- representation of a global variable name. In this chapter the terms global
- variable name and key are used interchangeably. A record refers to a key
- and its data.
+ The REGIONS section contain mappings of database region. A region is a
+ logical structure that holds information about a portion of a database,
+ such as key-size and record-size. A key is the internal representation of
+ a global variable name. In this chapter the terms global variable name and
+ key are used interchangeably. A record refers to a key and its data.
A Global Directory must have at least one region. A region only maps to a
single segment. More than one name may map to a region.
@@ -368,15 +397,16 @@
A region name:
o Can include alphanumerics, dollar signs ($), and underscores ( _ ).
- o Can have from 1 to 16 characters.
+ o Can have from 1 to 31 characters.
GDE automatically converts region names to uppercase, and uses DEFAULT for
the default region name.
- SEGMENT
+ SEGMENTS
- A segment defines file-related database storage characteristics. A segment
- must map to a single file. A segment can be mapped by only one region.
+ The SEGMENTS section contains mappings for segments. A segment defines
+ file-related database storage characteristics. A segment must map to a
+ single file. A segment can be mapped by only one region.
GT.M uses a segment to define a physical file and access method for the
database stored in that file.
@@ -384,7 +414,7 @@
A segment-name:
o Can include alphanumerics, dollar signs ($), and underscores ( _ )
- o Can have from one to 16 characters
+ o Can have from one to 31 characters
GDE automatically converts segment names to uppercase. GDE uses DEFAULT
for the default segment name.
@@ -396,9 +426,9 @@
disk.
By default, GDE uses the file-name mumps.dat for the DEFAULT segment. GDE
- adds the .dat to the file name when you do not specify an extension.
- Generally, avoid non-graphic and punctuation with potential semantic
- significance to the file system in file names as they tend to produce
+ adds the .dat to the file name when you do not specify an extension. Avoid
+ non-graphic and punctuation characters with potential semantic
+ significance to the file system in file names as they will produce
operational difficulties.
3 Example_of_a_Basic_Mapping
@@ -415,7 +445,7 @@
o ADD region cusreg, if it does not exist.
- GDE> add -region cusreg -d=cusseg
+ GDE> add -region cusreg -dynamic=cusseg
This creates the region cusreg and connects it to the segment cusseg.
-d[ynamic] is a required qualifier that takes the associated
@@ -423,34 +453,32 @@
o ADD segment cusreg, if it does not exist, and link it to a file.
- GDE> add -segment cusseg -file=cus
+ GDE> add -segment cusseg -file=cus.dat
This creates the segment cusseg and connects it to the file cus.dat.
- To review the information you have added to the Global Directory, enter
- the command SHOW.
+ To review the information you have added to the Global Directory, use the
+ SHOW command.
- To perform a base consistency check in the configuration, enter the
- command VERIFY.
+ To perform a consistency check of the configuration, use the VERIFY
+ command.
- To exit the Global Directory and save your changes, enter the command
- EXIT. At this point, GDE performs an automatic verification. If
- successfully confirmed, the mappings and database specifications become
- part of the Global Directory, available for access by processes,
- utilities, and the run-time system.
+ To exit the Global Directory and save your changes, use the EXIT command.
+ GDE performs an automatic verification. If successful, the mappings and
+ database specifications become part of the Global Directory, available for
+ access by processes, utilities, and the run-time system.
Only MUPIP CREATE uses the database specifications; run-time processes and
- other utility functions use only the map and ignore the other information
- in a global directory.
+ other utility functions use only the map.
1 Commands
Commands
- This section describes the GDE commands. GDE allows abbreviations of
- commands. The section describing each command provides the minimum
- abbreviation for that command and a description of any qualifiers that are
- not object-related. The section discussing the object-type describes all
- the associated object-related qualifiers.
+ This section describes GDE commands. GDE allows abbreviations of commands.
+ The section describing each command provides the minimum abbreviation for
+ that command and a description of any qualifiers that are not
+ object-related. The section discussing the object-type describes all the
+ associated object-related qualifiers.
Command Syntax:
@@ -482,12 +510,13 @@
general format. For the applicable format, refer to the section explaining
each of these commands.
- Comments on the command line may be delimited by an exclamation mark (!).
+ Comments on command lines start with an exclamation mark (!) and run to
+ the end of line.
**Caution**
- An exclamation mark not enclosed in quotation marks ("") causes GDE to
- ignore the rest of that input line.
+ An exclamation mark not enclosed in quotation marks ("")(for example in a
+ subscript) causes GDE to ignore the rest of that input line.
2 at-sign
at-sign
@@ -500,8 +529,8 @@
@file-name
The file-name specifies the command file to execute. Use the file-name
- alone for a file in the current working directory, or specify the relative
- path, or the full path.
+ alone for a file in the current working directory or specify the relative
+ path or the full path.
GDE executes each line of the command file as if it were entered at the
terminal.
@@ -522,26 +551,181 @@
The format of the ADD command is one of the following:
- A[DD]-N[AME] name-space -R[EGION]=region-name
- A[DD]-R[EGION] region-name -D[YNAMIC]=segment-name [-REGION-qualifier...]
- A[DD]-S[EGMENT] segment-name [-SEGMENT-qualifier...] -F[ILE_NAME]=file-name
+ A[DD] -N[AME] namespace -R[EGION]=region-name
+ A[DD] -R[EGION] region-name -D[YNAMIC]=segment-name [-REGION-qualifier...]
+ A[DD] -S[EGMENT] segment-name [-SEGMENT-qualifier...] -F[ILE_NAME]=file-name
+ A[DD] -G[BLNAME] global-name [-GBLNAME-qualifier ...]
The ADD command requires specification of an object-type and object-name.
GDE supplies default values from the templates for qualifiers not
explicitly supplied in the command.
+ namespace specifies a global name or a global name with subscript(s) or a
+ global name with a subscript range in the form of
+ global[[*]|[(from-subscript:[to-subscript])]].
+
Name spaces and file-names are case-sensitive; other objects are not
case-sensitive.
+3 Name
+ Name
+
+ Maps a namespace to a region in the global directory. The format of the
+ ADD -NAME command is:
+
+ A[DD]-N[AME] namespace -R[EGION]=region-name
+
+ o You can map a global and its subtrees to different regions.
+ o You can also use colon (:) to map ranges of subscripted names and
+ their subtrees to a region. Ranges are closed on the left and open on
+ the right side of the colon. For example, add -name PRODAGE(0:10)
+ -region DECADE0 maps ^PRODAGE(0) to ^PRODAGE(9), assuming the
+ application always uses integer subscripts, to region DECADE0.
+ o You can also use $CHAR() and $ZCHAR() to specify unprintable
+ characters as subscripts. "" (an empty string) or no value (e.g. 20:
+ or :20 or :) specify open-ended ranges, which span, on the left, from
+ the first subscript ("") to, on the right, the last possible string.
+ o Regions that contain global variables sharing the same unsubscripted
+ name that span regions must use standard null collation; attempting to
+ use the deprecated original null collation produces an error.
+
+ Example:
+
+ GDE> add -name IMPL -region=OTHERMUMPS ! Map MUMPS implementations to OTHERMUMPS
+ GDE> add -name IMPL("GT.M") -region=MYMUMPS ! While mapping GT.M to MYMUMPS
+
+ These examples map an entire subtree of a global to a region.
+
+ Example:
+
+ GDE> add -name PRODAGE(0:10) -region=DECADE0 ! Ranges are closed on the left and open on the right
+ GDE> add -name PRODAGE(10:20) -region=DECADE1 ! PRODAGE(10) maps to DECADE1
+ GDE> add -name PRODAGE(20:30) -region=DECADE2
+
+ This example uses a colon (:) to map ranges of subscripted names and their
+ subtrees to a region. Note that ranges are specific numbers or strings -
+ GDE does not support wildcards (using "*") in ranges.
+
+ Example:
+
+ GDE> add -name=PRODAGE(:10) -region=DECADE0 ! This line and the next are equivalent
+ GDE> add -name PRODAGE("":10) -region=DECADE0 ! numbers up to, but not including, 10
+ GDE> add -name PRODAGE(20:) -region=DECADE2 ! 20 thru all numbers (> 20) + strings
+ GDE> add -name PRODAGE(20:"") -region=DECADE2 ! same as the add just above
+
+ These examples demonstrate the use of $CHAR() and $ZCHAR() to specify
+ unprintable characters; Notice that the arguments are positive integers
+ (exponential - E syntax not allowed), and valid code points for $CHAR() or
+ in range for $ZCHAR(), both with respect to the current $ZCHSET. Also, ""
+ (an empty string) or no value (e.g. 20: or :20 or :) specify open-ended
+ ranges, which span, on the left, from the first subscript ("") to, on the
+ right, the last possible string.
+
+ Example:
+
+ GDE> add -name MODELNUM -region=NUMERIC
+ GDE> add -name MODELNUM($char(0):) -region=STRING
+
+ This example map numeric subscripts and strings to separate regions.
+
+ Example:
+
+ GDE> add -name DIVISION("Europe","a":"m") -region EUROPEAL
+ GDE> add -name DIVISION("Europe","m":"z") -region EUROPEM
+ GDE> add -name DIVISION("Australia") -region AUSTRALIA
+ GDE> add -name DIVISION("USA","South","a":"m") -region USSAL
+ GDE> add -name DIVISION("USA","South","m":"{") -region USSMZ
+ GDE> add -name DIVISION("USA","WestCoast") -region USWC
+
+ This example maps global variables with the same unsubscripted name at
+ multiple subscript levels.
+
+ Example:
+
+ GDE> add -name x -region=REG1
+ GDE> add -name x(5) -region=REG1
+ GDE> add -name x(5,10:) -region=REG2
+ GDE> add -name x(5:20) -region=REG2
+ GDE> add -name x(20) -region=REG2
+ GDE> add -name x(20,40) -region=REG2
+ GDE> add -name x(20,40,50:) -region=REG3
+ GDE> add -name x(20,40:) -region=REG3
+ GDE> add -name x(20:) -region=REG3
+
+ This example performs the following mapping:
+
+ o from ^x, upto but not including ^x(5,10), maps to REG1
+ o from ^x(5,10), upto but not including ^x(20,40,50), maps to to REG2
+ o from ^x(20,40,50) through the last subscript in ^x maps to REG 3
+
+3 Segment
+ Segment
+
+ Maps a segment to a database file. The syntax of the ADD -SEGMENT command
+ is:
+
+ A[DD]-S[EGMENT] segment-name [-SEGMENT-qualifier...] -F[ILE_NAME]=file-name
+
Example:
GDE> add -segment temp -file_name=scratch
This command creates a segment-name TEMP and maps it to the file
- scratch.dat in the current working directory. However, if you specify
- scratch is as the file-name, in other words specify it in the form of an
- environment variable, GT.M finds the file using the translation of that
- environment variable.
+ scratch.dat in the current working directory. However, if you were to
+ specify scratch as the file-name, in other words, an environment variable,
+ each process uses the file using the translation of that environment
+ variable at run-time.
+
+3 Region
+ Region
+
+ Maps a region to a segment. The syntax of the ADD -REGION command is:
+
+ A[DD]-R[EGION] region-name -D[YNAMIC]=segment-name [-REGION-qualifier...]
+
+3 Gblname
+ Gblname
+
+ Provides a mechanism to specify the collation for global variables sharing
+ the same unsubscripted name. Specifying a collation is necessary for
+ globals that span multiple regions and and use an alternate collation.
+ Because the global name EURCentral (described in the Introduction section)
+ uses an alternate collation, it requires an entry in the GBLNAME section.
+ The format of the ADD -GBLNAME command is:
+
+ A[DD] -G[BLNAME] -C[OLLATION]=collation_number
+
+ o Because string subscripts are subject to collation (the unsubscripted
+ portion of a global variable name and numeric subscripts are not), GDE
+ needs to know the collation sequence number associated with each
+ unsubscripted global variable name. M standard collation (the default)
+ has a collation number of zero (0). As a consequence, when you use
+ alternative collation(s) (other than 0), the collation transforms must
+ be available to GDE in the same way as they are to other GT.M
+ components. All of a global (all nodes sharing the same unsubscripted
+ global name) must have a single collation, which is implicitly the
+ case for globals that do not span multiple regions.
+ o Globals that do not span multiple regions and do not have any
+ collation characteristics defined in the GBLNAME section of the global
+ directory take on the default collation characteristics defined in the
+ database region to which they map. On the other hand, globals that
+ span multiple regions have their collation implicitly (collation 0),
+ or explicitly, established by the GBLNAME section of the global
+ directory and cannot adopt a differing collation based on the region
+ collation characteristic. Because GT.M determines collation for
+ globals spanning multiple regions by the GBLNAME characteristic, which
+ cannot change once the database files are created, GDE reports
+ collation on many error messages.
+
+ Example:
+
+ GDE> add -gblname EURCentral -collation=1
+ GDE> show -gblname
+
+ *** GBLNAMES ***
+ Global Coll Ver
+ ------------------------------------------------------------------------------
+ EURCentral 1 0
2 Change
Change
@@ -551,9 +735,10 @@
The format of the CHANGE command is:
- C[HANGE]-N[AME] name-space -R[EGION]=new-region
+ C[HANGE]-N[AME] namespace -R[EGION]=new-region
C[HANGE]-R[EGION] region-name [-REGION-qualifier...]
C[HANGE]-S[EGMENT] segment-name [-SEGMENT-qualifier...]
+ C[HANGE] -G[BLNAME] -C[OLLATION]=collation_number
The CHANGE command requires specification of an object-type and
object-name.
@@ -585,26 +770,26 @@
variables except through extended references using an alternative global
directory that does not map to them. Note that GT.M replication does not
support global updates made with extended references, unless they actually
- map to the same file as they would with the master global directory of the
- instance.
+ map to a database file that is a part of the replicated instance.
The format of the DELETE command is:
- D[ELETE]-N[AME] name-space
- D[ELETE]-R[EGION] region-name
- D[ELETE]-S[EGMENT] segment-name
+ D[ELETE] -N[AME] namespace
+ D[ELETE] -R[EGION] region-name
+ D[ELETE] -S[EGMENT] segment-name
+ D[ELETE] -G[BLNAME] global-name
The DELETE command requires specification of an object-type and
object-name.
- Deleting a name removes the name-to-region mapping. Deleting a region
+ Deleting a name removes the namespace-to-region mapping. Deleting a region
unmaps all names mapped to the region. Deleting a segment unmaps the
region mapped to the segment.
You may map the deleted names to another region or the deleted region to
another segment using the CHANGE command.
- The default name-space (*) cannot be deleted.
+ The default namespace (*) cannot be deleted.
Example:
@@ -660,17 +845,18 @@
2 LOCks
LOCks
- The LOCKS command specifies the region into which GT.M maps locks on
- resource names not starting with a caret symbol (^). GDE maps locks on
- resource names, starting with a caret symbol (^), to the database region
- mapped for the global variable name matching the resource name.
+ The LOCKS command specifies the region into which GT.M maps "local"
+ locks(those with resource names not starting with a caret symbol ^). GDE
+ maps locks on resource names, starting with a caret symbol, to the
+ database region mapped for the global variable name matching the resource
+ name.
The format of the LOCKS command is:
LOC[KS] -R[EGION]=region-name
The LOCKS -REGION= qualifier allows specification of a region for local
- locks. By default, GDE maps local locks to the default region DEFAULT.
+ locks. By default, GDE maps local locks to the DEFAULT region .
Example:
@@ -679,6 +865,20 @@
This command maps all locks on resource names that don't start with the
caret symbol, "^" to the region main.
+ **Caution**
+
+ GT.M associates LOCKs for global names with the database region holding
+ the corresponding unsubscripted global name. Suppose a global called
+ ^EURWest spans multiple regions in multiple global directories, a command
+ like LOCK ^EURWest may not work in the same way as it would do if ^EURWest
+ did not span multiple regions. Before using a command like LOCK ^EURWest
+ where ^EURWest spans multiple regions in multiple directories, ensure that
+ the corresponding unsubscripted ^EURWest map to the same region in all the
+ global directories. Alternatively, you can use LOCK globalname (with no
+ leading up-arrow) and control LOCK interactions with the LOCKS global
+ directory characteristic or use transaction processing to eliminate the
+ use of LOCKs to protect global access.
+
2 LOG
LOG
@@ -732,14 +932,15 @@
2 Rename
Rename
- The RENAME command allows you to change a name-space, the name of a
- region, or the name of a segment.
+ The RENAME command allows you to change a namespace, the name of a region,
+ or the name of a segment.
The format of the RENAME command is:
- R[ENAME]-N[AME] old-name new-name
- R[ENAME]-R[EGION] old-region-name new-region-name
- R[ENAME]-S[EGMENT] old-segment-name new-segment-name
+ R[ENAME] -N[AME] old-name new-name
+ R[ENAME] -R[EGION] old-region-name new-region-name
+ R[ENAME] -S[EGMENT] old-segment-name new-segment-name
+ R[ENAME] -G[BLNAME] old-global-name new-global-name
The RENAME command requires specification of an object-type and two
object-names.
@@ -798,11 +999,12 @@
The format of the SHOW command is:
SH[OW] -C[OMMAND] -F[ILE]=[gde-command-file]
- SH[OW] -N[AME] [name-space]
+ SH[OW] -N[AME] [namespace]
SH[OW] -R[EGION] [region-name]
SH[OW] -S[EGMENT] [segment-name]
SH[OW] -M[AP] [-R[EGION]=region-name]
SH[OW] -T[EMPLATE]
+ SH[OW] -G[BLNAME]
SH[OW] -A[LL]
-COMMAND: Displays GDE commands that recreate the current Global Directory
@@ -812,8 +1014,25 @@
commands produced by -COMMAND. -FILE must must always appear after
-COMMAND.
- -NAME, -REGION, -SEGMENT, -MAP, -TEMPLATE, and -ALL are qualifiers that
- cause GDE to display selected portions of the Global Directory as follows:
+ Please consider using command files produced with the SHOW -COMMAND -FILE
+ for creating new regions and segments in a global directory as the
+ defaults come from the templates. If you inadvertently upgrade a global
+ directory, you can use SHOW -COMMAND to create a file of commands that you
+ can input to GDE with the prior GT.M release to recreate the prior global
+ directory file.
+
+ **Note**
+
+ When GDE encounters an error while executing the @command-file command, it
+ stops processing the command file and returns to the operator prompt,
+ which gives the operator the option of compensating for the error. If you
+ subsequently issue @command-file command again in the same session for the
+ same command-file, GDE resumes processing it at the line after the last
+ error.
+
+ -NAME, -REGION, -SEGMENT, -GBLNAME, -MAP, -TEMPLATE, and -ALL are
+ qualifiers that cause GDE to display selected portions of the Global
+ Directory as follows:
-MAP: Displays the current mapping of all names, regions, segments, and
files. This qualifier corresponds to the section of the SHOW report titled
@@ -844,12 +1063,13 @@
Example:
GDE>show -template
- *** TEMPLATES ***
- Std Inst
- Def Rec Key Null Null Freeze Qdb
- Region Coll Size Size Subs Coll Jnl on Error Rndwn
- ----------------------------------------------------------------------------------------------
- <default> 0 4080 255 NEVER Y Y DISABLED DISABLED
+
+ *** TEMPLATES ***
+ Std Inst
+ Def Rec Key Null Null Freeze Qdb
+ Region Coll Size Size Subs Coll Jnl on Error Rndwn
+ ----------------------------------------------------------------------------------------------------
+ <default> 0 4080 255 NEVER Y Y DISABLED DISABLED
Jnl File (def ext: .mjl) Before Buff Alloc Exten AutoSwitch
------------------------------------------------------------------------------------------
<default> <based on DB file-spec> Y 2308 2048 2048 8386560
@@ -860,34 +1080,79 @@
LOCK = 40
RES = 0
ENCR = OFF
+ MSLT =1024
<default> MM DYN 4096 5000 10000 DEFER
LOCK = 40
+ MSLT =1024
This displays only the TEMPLATES section of the Global Directory.
GDE>SHOW -command
- TEMPLATE -SEGMENT -ACCESS_METHOD=MM -BLOCK_SIZE=4096 -ALLOCATION=5000 -EXTENSION_COUNT=10000
- -LOCK_SPACE=40 -RESERVED_BYTES=0 -DEFER
- TEMPLATE -SEGMENT -ACCESS_METHOD=BG -BLOCK_SIZE=4096 -ALLOCATION=5000 -EXTENSION_COUNT=10000
- -LOCK_SPACE=40 -RESERVED_BYTES=0 -GLOBAL_BUFFER_COUNT=1000
- TEMPLATE -REGION -RECORD_SIZE=4080 -KEY_SIZE=255 -NULL_SUBSCRIPTS=NEVER -STDNULLCOLL
- -NOINST_FREEZE_ON_ERROR -NOQDBRUNDOWN
- TEMPLATE -REGION
- -JOURNAL=(BEFORE_IMAGE,BUFFER_SIZE=2308,ALLOCATION=2048,EXTENSION=2048,AUTOSWITCHLIMIT=8386560)
+ TEMPLATE -REGION -COLLATION_DEFAULT=0
+ TEMPLATE -REGION -NOINST_FREEZE_ON_ERROR
+ TEMPLATE -REGION -JOURNAL=(ALLOCATION=2048,AUTOSWITCHLIMIT=8386560,BEFORE_IMAGE,BUFFER_SIZE=2308,EXTENSION=2048)
+ TEMPLATE -REGION -KEY_SIZE=64
+ TEMPLATE -REGION -NULL_SUBSCRIPTS=NEVER
+ TEMPLATE -REGION -NOQDBRUNDOWN
+ TEMPLATE -REGION -RECORD_SIZE=256
+ TEMPLATE -REGION -STDNULLCOLL
!
- LOCKS -REGION=DEFAULT
-
- CHANGE -REGION DEFAULT -DYNAMIC=DEFAULT -COLLATION_DEFAULT=0 -RECORD_SIZE=4080 -KEY_SIZE=255
- -NULL_SUBSCRIPTS=NEVER -STDNULLCOLL
- -JOURNAL=(BEFORE_IMAGE,BUFFER_SIZE=2308,ALLOCATION=2048,EXTENSION=2048,AUTOSWITCHLIMIT=8386560,
- FILE="$gtmdir/$gtmver/g/gtm.mjl") -NOINST_FREEZE_ON_ERROR -NOQDBRUNDOWN
+ TEMPLATE -REGION -NOJOURNAL
+ !
+ TEMPLATE -SEGMENT -ACCESS_METHOD=BG
+ TEMPLATE -SEGMENT -ALLOCATION=100
+ TEMPLATE -SEGMENT -BLOCK_SIZE=1024
+ TEMPLATE -SEGMENT -NOENCRYPTION_FLAG
+ TEMPLATE -SEGMENT -EXTENSION_COUNT=100
+ TEMPLATE -SEGMENT -GLOBAL_BUFFER_COUNT=1024
+ TEMPLATE -SEGMENT -LOCK_SPACE=40
+ TEMPLATE -SEGMENT -MUTEX_SLOTS=1024
+ TEMPLATE -SEGMENT -RESERVED_BYTES=0
!
- CHANGE -SEGMENT DEFAULT -ACCESS_METHOD=BG -BLOCK_SIZE=4096 -ALLOCATION=5000 -EXTENSION_COUNT=10000
- -LOCK_SPACE=40 -RESERVED_BYTES=0 -GLOBAL_BUFFER_COUNT=1000 -FILE=$gtmdir/$gtmver/g/gtm.dat
+ TEMPLATE -SEGMENT -ACCESS_METHOD=MM
+ TEMPLATE -SEGMENT -ALLOCATION=100
+ TEMPLATE -SEGMENT -BLOCK_SIZE=1024
+ TEMPLATE -SEGMENT -DEFER
+ TEMPLATE -SEGMENT -NOENCRYPTION_FLAG
+ TEMPLATE -SEGMENT -EXTENSION_COUNT=100
+ TEMPLATE -SEGMENT -GLOBAL_BUFFER_COUNT=1024
+ TEMPLATE -SEGMENT -LOCK_SPACE=40
+ TEMPLATE -SEGMENT -MUTEX_SLOTS=1024
+ TEMPLATE -SEGMENT -RESERVED_BYTES=0
+ !
+ TEMPLATE -SEGMENT -ACCESS_METHOD=BG
+ !
+ DELETE -REGION DEFAULT
+ DELETE -SEGMENT DEFAULT
+ ADD -REGION AUSREG -DYNAMIC_SEGMENT=AUSSEG
+ ADD -REGION DEFAULT -DYNAMIC_SEGMENT=DEFAULT
+ ADD -REGION FRREG -DYNAMIC_SEGMENT=FRSEG
+ ADD -REGION POREG -DYNAMIC_SEGMENT=POSEG
+ ADD -REGION UKREG -DYNAMIC_SEGMENT=UKSEG
+ ADD -REGION USSALREG -DYNAMIC_SEGMENT=USSALSEG
+ ADD -REGION USSMZREG -DYNAMIC_SEGMENT=USSMZSEG
+ !
+ ADD -SEGMENT AUSSEG -FILE_NAME="AUS.dat"
+ ADD -SEGMENT DEFAULT -FILE_NAME="gtm.dat"
+ ADD -SEGMENT FRSEG -FILE_NAME="France.dat"
+ ADD -SEGMENT POSEG -FILE_NAME="Poland.dat"
+ ADD -SEGMENT UKSEG -FILE_NAME="UK.dat"
+ ADD -SEGMENT USSALSEG -FILE_NAME="USSAL.dat"
+ ADD -SEGMENT USSMZSEG -FILE_NAME="USSMZ.dat"
+ !
+ ADD -GBLNAME EURCentral -COLLATION=1
+ !
+ LOCKS -REGION=DEFAULT
+ ADD -NAME Australia -REGION=AUSREG
+ ADD -NAME EURCentral("Poland") -REGION=POREG
+ ADD -NAME EURWest("France") -REGION=FRREG
+ ADD -NAME EURWest("UK") -REGION=UKREG
+ ADD -NAME US("South","a":"m") -REGION=USSALREG
+ ADD -NAME US("South","m":"{") -REGION=USSMZREG
!
- This command displays the GDE commands to recreate the current global
- directory state.
+ This command displays the GDE commands to recreate the spanning region
+ example described in the Introduction section.
2 Template
Template
@@ -930,10 +1195,11 @@
The format of the VERIFY command is:
V[ERIFY]
- V[ERIFY] -N[AME] [name-space]
+ V[ERIFY] -N[AME] [namespace]
V[ERIFY] -R[EGION] [region-name]
V[ERIFY] -S[EGMENT] [segment-name]
V[ERIFY] -M[AP]
+ V[ERIFY] -G[BLNAME]
V[ERIFY] -T[EMPLATE]
V[ERIFY] -A[LL]
@@ -981,13 +1247,13 @@
The minimum length is one alphabetic character.
- The maximum length is 16 alphanumeric characters.
+ The maximum length is 31 alphanumeric characters.
Example:
GDE> add -name a* -region=areg
- This command creates the name-space a*, if it does not exist, and maps it
+ This command creates the namespace a*, if it does not exist, and maps it
to the region areg.
Summary
@@ -1032,7 +1298,7 @@
The minimum length is one alphabetic character.
- The maximum length is 16 alphanumeric characters.
+ The maximum length is 31 alphanumeric characters.
-K[EY_SIZE]=size in bytes
@@ -1042,16 +1308,11 @@
The minimum KEY_SIZE is three bytes.
- The maximum KEY_SIZE is 1019 bytes.
+ The maximum KEY_SIZE is 1,019 bytes.
When determining the maximum key size, applications should consider the
following:
- * A key must fit within one database block and the maximum KEY_SIZE is
- limited to 40 bytes less than the block size. For example, a 1024 byte
- block can support a maximum KEY_SIZE of 984 bytes and a 1536 byte
- block size is the smallest that supports a maximum KEY_SIZE of 1019
- bytes.
* GT.M uses packed decimal representation for numeric subscripts which
may be larger or smaller than the original representation.
* GT.M substitutes an element terminator for the caret (^), any comma
@@ -1072,8 +1333,8 @@
that global across multiple database blocks. In the event a global
variable node spans multiple blocks, and the process is not already within
a TP transaction, the GT.M run-time system automatically and transparently
- performs the entire operation within an implicit TP transaction (just as
- is the case with triggers).
+ performs the entire operation within an implicit TP transaction (as it
+ does for Triggers).
The minimum RECORD_SIZE is zero. A RECORD_SIZE of zero only allows a
global variable node that does not have a value. A typical use of a global
@@ -1110,7 +1371,9 @@
subscripts.
If NOSTDNULLCOLL is specified, null subscripts collate between numeric and
- string subscripts.
+ string subscripts. FIS strongly recommends that you use STDNULL and
+ against using this non-standard null collation, which is the default for
+ historical reasons.
-[NO]INST[_FREEZE_ON_ERROR]
@@ -1133,22 +1396,26 @@
Note that with QDBRUNDOWN there is a possibility of race condition that
might leave the database fileheader and IPC resources in need of cleanup.
Although QDBRUNDOWN minimizes the probability of such a race condition, it
- cannot eliminate it. When using QDBRUNDOWN, FIS recommends an explicit
- MUPIP RUNDOWN of the database file after the last process exits, to ensure
- the cleanup of database fileheader and IPC resources.
+ cannot eliminate it. FIS recommends restricting QDBRUNDOWN usage to
+ special circumstances such as benchmarking and recommends NOQDBRUNDOWN for
+ normal GT.M usage. When using QDBRUNDOWN, FIS recommends an explicit MUPIP
+ RUNDOWN of the database file after the last process exits, to ensure the
+ cleanup of database fileheader and IPC resources.
-[NO]J[OURNAL][=journal-option-list]
- Specifies whether the database file allows journaling. If it does, this
- qualifier establishes characteristics for the journal file.
+ This qualifier establishes characteristics for the journal file on newly
+ created databases.
-NOJOURNAL specifies that updates to the database file are not journaled.
-NOJOURNAL does not accept an argument assignment.
-JOURNAL specifies that journaling is allowed. -JOURNAL takes one or more
arguments in a journal-option-list. The journal-option-list contains
- keywords separated with commas (,) enclosed in parentheses ( ). If the
- list contains only one keyword, the parentheses are optional.
+ keywords separated with commas (,) enclosed in parentheses ( ) with
+ file-names quoted (for example, change -region test
+ -journal=(before,file="foo") . If the list contains only one keyword, the
+ parentheses and quotes are optional.
Although you do not have to establish the criteria for your journaling
process at this point, it is efficient to do so, even if you are not
@@ -1171,14 +1438,16 @@
The following section describes some -JOURNAL options.
+ -AU[TOSWITCHLIMIT]=blocks
+
Specifies the limit on the size of a journal file. When the journal file
- size reaches the limit, GT.M automatically performs an implicit online
- switch to a new journal file.
+ size reaches the limit, GT.M automatically switches to a new journal file
+ with a back-pointer to the prior journal file.
-[NO]BE[FORE_IMAGE]
- [NO]BEFORE_IMAGE controls whether the journal should capture before images
- of information that an update is about to modify.
+ [NO]BEFORE_IMAGE controls whether the journal should include before-image
+ records.
The BEFORE_IMAGE option is required if you plan to consider "roll-back"
(Backward) recovery of the associated database file or if you plan to use
@@ -1188,7 +1457,9 @@
Specifies the name of the journal file.
- The name should always be enclosed in quotation marks in this context.
+ Unless the name is the sole journaling option, and is the last parameter
+ on the line, it should always be enclosed in quotation marks in this
+ context.
Journal file-specifications-names are limited to 255 characters.
@@ -1197,10 +1468,15 @@
By default, GDE uses a journal file extension of .mjl.
- JOL Summary
+ Journal Options Summary
With GDE, you can create the journal files and define the journal
- parameters; however, you must use MUPIP SET to actually enable journaling.
+ parameters; however, you must use MUPIP SET to explicitly turn it ON, and
+ you must specify BEFORE/NOBEFORE at that time.
+
+ Example:
+
+ CHANGE -REGION DEFAULT -JOURNAL=(ALLOCATION=2048,AUTOSWITCHLIMIT=8386560,BEFORE_IMAGE,BUFFER_SIZE=2308,EXTENSION=2048)
Summary
@@ -1217,7 +1493,7 @@
|--------------------------------------------+----------+---------+-----------|
|-D[YNAMIC_SEGMENT] =segment-name (char) |- |1 |16 |
|--------------------------------------------+----------+---------+-----------|
- |-K[EY_SIZE]=size in bytes (integer) |64 |3 |1019 |
+ |-K[EY_SIZE]=size in bytes (integer) |64 |3 |1,019 |
|--------------------------------------------+----------+---------+-----------|
|-R[ECORD_SIZE]=size in bytes (integer) |256 |7 |1,048,576 |
| | | |(1 MiB) |
@@ -1260,15 +1536,16 @@
GT.M has no control over the timing of disk updates, therefore there
is a greater reliance on the OS/file system for database performance.
- * MM supports NOBEFORE_IMAGE journaling only. GT.M triggers an
- error if you use MM with BEFORE_IMAGE Journaling. MM also
- supports MUPIP FORWARD -RECOVER and MUPIP JOURNAL -ROLLBACK with
- the -RESYNC or -FETCHRESYNC qualifiers to generate lost and
- broken transaction files. For more information, see the
- Journaling chapter.
+ * MM supports NOBEFORE_IMAGE journaling only. GT.M issues an error
+ if you use MM with BEFORE_IMAGE Journaling. MM also supports
+ MUPIP FORWARD -RECOVER and MUPIP JOURNAL -ROLLBACK with the
+ -RESYNC or -FETCHRESYNC qualifiers to generate lost and broken
+ transaction files. For more information, see the Journaling and
+ Replication chapters.
* MM does not support backward recovery/rollback.
- * MM is a possible choice when you need performance advantage in
- situations where the above restrictions are acceptable.
+ * Depending on your file system, MM may be an option when you need
+ performance advantage in situations where the above restrictions
+ are acceptable.
o GDE maintains a separate set of segment qualifier values for each
ACCESS_METHOD.
@@ -1342,11 +1619,11 @@
**Note**
- FIS recommends against using databases with block sizes larger than 16KB.
+ FIS recommends against using databases with block sizes larger than 16KiB.
If a specific global variable has records that have large record sizes,
FIS recommends placing that global variable in a file by itself with large
block sizes and using more appropriate block sizes for other global
- variables. 4KB and 8KB are popular database block sizes.
+ variables. 4KiB and 8KiB are popular database block sizes.
By default, GDE uses a BLOCK_SIZE of 1024 bytes.
@@ -1374,13 +1651,22 @@
The minimum EXTENSION is zero blocks.
+ When a database file with automatic extension disabled (EXTENSION_COUNT=0)
+ starts to get full, GT.M records the FREEBLSLOW warning in the system log.
+ So as to not compromise performance, GT.M checks whenever the master bit
+ map must be updated to show that a local bit map is full, and issues the
+ warning if there are fewer than 512 free blocks or if the number of free
+ blocks is less than total blocks/32. This means that for databases whose
+ size is 512 blocks or less the warning comes at the last successful update
+ before the database becomes full.
+
The maximum EXTENSION is 65,535 blocks.
By default, GDE uses an EXTENSION of 100 blocks.
Like allocation, the default extension amount was chosen for initial
- development and experimentation with GT.M projects. Use larger extensions
- for larger files. Because multiple file extensions adversely affect
+ development and experimentation. Use larger extensions for larger actual
+ applications. Because multiple file extensions adversely affect
performance, set up extensions appropriate to the file allocation.
-F[ILE_NAME]=file-name
@@ -1390,7 +1676,9 @@
The maximum file name length is 255 characters.
By default, GDE uses a file-name of mumps followed by the default
- extension, which is .dat.
+ extension, which is .dat. You can specify any filename and extension of
+ your choice for a database file as long as it is valid on your operating
+ system.
-G[LOBAL_BUFFER_COUNT]=size
@@ -1401,9 +1689,9 @@
Choose the settings for this qualifier carefully. Small numbers of global
buffers tend to throttle database performance. However, if your system has
limited memory and the database file traffic is not heavy enough to hold
- the cache in memory, increasing GLOBAL_BUFFER_COUNT may trigger paging.
+ the cache in RAM, increasing GLOBAL_BUFFER_COUNT may trigger paging.
- If database global buffers are paged out, it may result in poor
+ If database global buffers are paged out, it will result in poor
performance. Therefore, do not increase this factor to a large value
without careful observation.
@@ -1423,16 +1711,17 @@
application.
Generally, you should increase the number of GLOBAL_BUFFERs for production
- GDS databases. This is because GT.M uses the shared memory database cache
- associated with each GDS file for the majority of caching.
+ GDS database files. This is because GT.M uses the shared memory database
+ cache associated with each GDS file for the majority of caching.
The minimum GLOBAL_BUFFER_COUNT for BG is 64 blocks.
- The maximum for GLOBAL_BUFFER_COUNT for BG is 2147483647 blocks, but may
- vary depending on your platform.
+ The maximum for GLOBAL_BUFFER_COUNT for BG is 2,147,483,647 blocks, but
+ may vary depending on your platform.
- By default, GDE uses a GLOBAL_BUFFER_COUNT that is appropriate for the
- typical size of the platform.
+ By default, GDE uses a GLOBAL_BUFFER_COUNT that is appropriate for initial
+ development use on each platform, but probably too small for production
+ applications.
**Note**
@@ -1460,19 +1749,29 @@
processes waiting for locks. To estimate lock space needs, here is a rule
of thumb:
- o 1.5KB overhead for the lock space, plus
+ o 1.5KiB overhead for the lock space, plus
o 640 bytes for each lock base name, plus
o 128 bytes for each subscript, plus
o 128 bytes for each waiting process.
- Generally, you would limit LOCK_SPACE when memory is scarce or you want to
- be made aware of unexpected levels of LOCK usage. For most other cases,
- there is no reason to limit the LOCK_SPACE. If you are introducing new
- code, FIS recommends using TSTART and TCOMMIT as a more efficient
+ Generally, you would limit LOCK_SPACE only when memory is scarce or you
+ want to be made aware of unexpected levels of LOCK usage. For most other
+ cases, there is no reason to limit the LOCK_SPACE. If you are introducing
+ new code, FIS recommends using TSTART and TCOMMIT as a more efficient
alternate for most LOCKs because it pushes the responsibility for
Isolation onto GT.M, which internally manages them with optimistic
algorithms.
+ -M[UTEX_SLOTS]=integer
+
+ Specifies the number of mutex slots for a database file. GT.M uses mutex
+ slots to manage database contention. FIS recommends you configure the
+ slots to cover the maximum number of processes you expect to concurrently
+ access the database file, as an insufficient number of slots can lead to
+ much steeper and more severe degradation of performance under heavy loads.
+ The minimum is 1Ki and the maximum is 32Ki. The default of 1Ki should be
+ appropriate for most situations.
+
-R[ESERVED_BYTES]=size
Specifies the size to be reserved in each database block. RESERVED_BYTES
@@ -1497,35 +1796,72 @@
+------------------------------------------------------------------------+
| GDE SEGMENT Qualifiers |
|------------------------------------------------------------------------|
- | QUALIFIER | DEFAULT | MIN | MAX |
+ | QUALIFIER | DEFAULT | MIN | MAX |
|------------------------------------------------------------------------|
| ** BLOCK_SIZE minus the size of the block header |
|------------------------------------------------------------------------|
| * May vary by platform |
|------------------------------------------------------------------------|
- | -AC[CESS_METHOD]=BG|MM | BG | - | - |
- |-------------------------------+-----------+-----+----------------------|
- | -AL[LOCATION]=size (blocks) | 100 | 10 | 1,040,187,392(992Mi) |
- |-------------------------------+-----------+-----+----------------------|
- | -BL[OCK_SIZE]=size (bytes) | 1024 | 512 | 65024 |
- |-------------------------------+-----------+-----+----------------------|
- | -[NO]EN[CRYPTION] | 0 | | |
- |-------------------------------+-----------+-----+----------------------|
- | -EX[TENSION_COUNT]=size | 100 | 0 | 65,535 |
- | (blocks) | | | |
- |-------------------------------+-----------+-----+----------------------|
- | -F[ILE_NAME]=file-name | mumps.dat | - | 255 |
- | (chars) | | | |
- |-------------------------------+-----------+-----+----------------------|
- | -G[LOBAL_BUFFER_COUNT]=size | 1024* | 64 | 2147483647 |
- | (blocks) | | | |
- |-------------------------------+-----------+-----+----------------------|
- | -L[OCK_SPACE]=size (pages) | 40 | 10 | 65536 |
- |-------------------------------+-----------+-----+----------------------|
- | -R[ESERVED_BYTES]=size | 0 | 0 | block size-7 |
- | (bytes) | | | |
+ | -AC[CESS_METHOD]=BG|MM | BG | - | - |
+ |-----------------------------+-----------+-------+----------------------|
+ | -AL[LOCATION]=size (blocks) | 100 | 10 | 1,040,187,392(992Mi) |
+ |-----------------------------+-----------+-------+----------------------|
+ | -BL[OCK_SIZE]=size (bytes) | 1,024 | 512 | 65,024 |
+ |-----------------------------+-----------+-------+----------------------|
+ | -[NO]EN[CRYPTION] | 0 | | |
+ |-----------------------------+-----------+-------+----------------------|
+ | -EX[TENSION_COUNT]=size | 100 | 0 | 65,535 |
+ | (blocks) | | | |
+ |-----------------------------+-----------+-------+----------------------|
+ | -F[ILE_NAME]=file-name | mumps.dat | - | 255 |
+ | (chars) | | | |
+ |-----------------------------+-----------+-------+----------------------|
+ | -G[LOBAL_BUFFER_COUNT]=size | 1024* | 64 | 2,147,483,647 |
+ | (blocks) | | | |
+ |-----------------------------+-----------+-------+----------------------|
+ | -L[OCK_SPACE]=size (pages) | 40 | 10 | 65536 |
+ |-----------------------------+-----------+-------+----------------------|
+ | -M[UTEX_SLOTS]=integer | 1,024 | 1,024 | 32,768 |
+ |-----------------------------+-----------+-------+----------------------|
+ | -R[ESERVED_BYTES]=size | 0 | 0 | block size-7 |
+ | (bytes) | | | |
+------------------------------------------------------------------------+
+2 Gblname_Qualifiers
+ Gblname Qualifiers
+
+ The following -GBLNAME qualifier can be used with the ADD, CHANGE, or
+ TEMPLATE commands.
+
+ -C[OLLATION]=collation_number
+
+ Specifies the collation number for a global name; a value of 0 specifies
+ standard M collation. The first time that a GT.M processes accesses a
+ global variable name in a database file, it determines the collation
+ sequence as follows:
+
+ o If a Global Variable Tree (GVT) exists (that is, global variable nodes
+ exist, or have previously existed, even if they have been KILL'd), use
+ the existing collation:
+
+ o If there is a collation specified in the Directory Tree (DT) for
+ that variable, use it after confirming that this matches the
+ collation in the global directory.
+ o else (that is, there is no collation specified in the DT):
+
+ + If there is collation specified for that global variable in
+ the global directory use it
+ + else if there is a default for that database file, use it
+ + else (that is, neither exists), use standard M collation
+
+ o else (that is, a GVT does not exist, which in turn means there is no
+ DT):
+
+ o If there is collation specified for that global variable in the
+ global directory use it
+ o else, if there is a default for that database file, use it
+ o else (that is, neither exists), use standard M collation
+
1 Summary
Summary
@@ -1542,7 +1878,7 @@
|------------------------------------------------------------------------|
| @ | N/A | file-name |
|------------+------------------+----------------------------------------|
- | | | name-space |
+ | | | namespace |
| A[DD] | -N[AME] | |
| | | -R[EGION]=region-name |
|------------+------------------+----------------------------------------|
@@ -1556,7 +1892,11 @@
| | | -F[ILE_NAME]=file-name |
| | | [-SEGMENT-qualifier...] |
|------------+------------------+----------------------------------------|
- | | | name-space |
+ | | | global-name |
+ | - | -G[BLNAME] | |
+ | | | -C[OLLATION]=collation |
+ |------------+------------------+----------------------------------------|
+ | | | namespace |
| C[HANGE] | -N[AME] | |
| | | -R[EGION]=new-region |
|------------+------------------+----------------------------------------|
@@ -1568,12 +1908,20 @@
| - | -S[EGMENT] | |
| | | [-SEGMENT-qualifier] |
|------------+------------------+----------------------------------------|
- | D[ELETE] | -N[AME] | name-space |
+ | | | global-name |
+ | - | -G[BLNAME] | |
+ | | | -C[OLLATION]=collation |
+ |------------+------------------+----------------------------------------|
+ | D[ELETE] | -N[AME] | namespace |
|------------+------------------+----------------------------------------|
| - | -R[EGION] | region-name |
|------------+------------------+----------------------------------------|
| - | -S[EGMENT] | segment-name |
|------------+------------------+----------------------------------------|
+ | | | global-name |
+ | - | -G[BLNAME] | |
+ | | | -C[OLLATION]=collation |
+ |------------+------------------+----------------------------------------|
| E[XIT] | N/A | N/A |
|------------+------------------+----------------------------------------|
| HE[LP] | N/A | Keyword |
@@ -1592,14 +1940,22 @@
|------------+------------------+----------------------------------------|
| - | -S[EGMENT] | old-seg-name new-seg-name |
|------------+------------------+----------------------------------------|
+ | | | global-name |
+ | - | -G[BLNAME] | |
+ | | | -C[OLLATION]=collation |
+ |------------+------------------+----------------------------------------|
| SE[TGD] | N/A | -F[ILE]=file-name [-Q[UIT]] |
|------------+------------------+----------------------------------------|
- | SH[OW] | -N[AME] | [name-space] |
+ | SH[OW] | -N[AME] | [namespace] |
|------------+------------------+----------------------------------------|
| - | -R[EGION] | [region-name] |
|------------+------------------+----------------------------------------|
| - | -S[EGMENT] | [segment-name] |
|------------+------------------+----------------------------------------|
+ | | | global-name |
+ | - | -G[BLNAME] | |
+ | | | -C[OLLATION]=collation |
+ |------------+------------------+----------------------------------------|
| - | -M[AP] | [R[EGION]=region-name] |
|------------+------------------+----------------------------------------|
| - | T[EMPLATE] | N/A |
@@ -1610,12 +1966,16 @@
|------------+------------------+----------------------------------------|
| - | -S[EGMENT] | [ -SEGMENT-qualifier...] |
|------------+------------------+----------------------------------------|
- | V[ERIFY] | -N[AME] | [name-space] |
+ | V[ERIFY] | -N[AME] | [namespace] |
|------------+------------------+----------------------------------------|
| - | -R[EGION] | [region-name] |
|------------+------------------+----------------------------------------|
| - | -S[EGMENT] | [segment-name] |
|------------+------------------+----------------------------------------|
+ | | | global-name |
+ | - | -G[BLNAME] | |
+ | | | -C[OLLATION]=collation |
+ |------------+------------------+----------------------------------------|
| - | -M[AP] | N/A |
|------------+------------------+----------------------------------------|
| - | -T[EMPLATE] | N/A |
@@ -1629,59 +1989,64 @@
The following table summarizes all qualifiers for the ADD, CHANGE, and
TEMPLATE commands. The defaults are those supplied by FIS.
- +------------------------------------------------------------------------------------------------+
- | GDE Command Qualifiers |
- |------------------------------------------------------------------------------------------------|
- | QUALIFIER | DEF | MIN | MAX | NAM | REG | SEG |
- |------------------------------------------------------------------------------------------------|
- | * DEFAULT is the default region- and segment-name |
- | ** MUMPS is the default file-name |
- | *** May vary by platform |
- | **** -NONULL_SUBSCRIPTS |
- |------------------------------------------------------------------------------------------------|
- |-AC[CESS_METHOD]=code |BG |- |- |- |- |X |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-AL[LOCATION]=size(blocks) |100 |10 |1040187392(992Mi) |- |- |X |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-BL[OCK_SIZE]=size(bytes) |1024 |512 |65024 |- |- |X |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-C[OLLATION_DEFAULT]=id-number (integer) |0 |0 |255 |- |X |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-D[YNAMIC_SEGMENT]=segment-name (chars) |* |1A |16A/N |- |X |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-EX[TENSION_COUNT]=size (blks) |100 |0 |65535 |- |- |X |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-F[ILE_NAME]=file-name (chars) |** |1A |255A/N |- |- |X |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-G[LOBAL_BUFFER_COUNT]=size (blocks) |1024 |64 |2147483647 *** |- |- |X |
- | |*** | | | | | |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-K[EY_SIZE]=size (bytes) |64 |3 |1019 |- |X |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-L[OCK_SPACE]=size (pages) |40 |10 |65536 |- |- |X |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-[NO]INST[_FREEZE_ON_ERROR] |FALSE |- |- |- |X |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-[NO]Q[DBRUNDOWN] |FALSE |- |- |- |X |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-[NO]J[OURNAL]=option-list |-NOJ |- |- |- |X |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-N[ULL_SUBSCRIPTS]=[ALWAYS|NEVER|EXISTING] |NEVER |- |- |- |X |- |
- | |or ****| | | | | |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-[NO]STDNULLCOLL[=TRUE|FALSE] |FALSE |- |- |- |X |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-R[ECORD_SIZE]=size (bytes) |256 |7 |1048576 |- |X |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-R[EGION] region-name (chars) |* |1A |16A/N |X |- |- |
- |--------------------------------------------+-------+-----+-------------------+-----+-----+-----|
- |-R[ESERVED_BYTES]=size (bytes) |0 |0 |blocksize |- |- |X |
- +------------------------------------------------------------------------------------------------+
+ +-----------------------------------------------------------------------------------------------------+
+ | GDE Command Qualifiers |
+ |-----------------------------------------------------------------------------------------------------|
+ | QUALIFIER | DEF | MIN | MAX | NAM | REG | SEG |
+ |-----------------------------------------------------------------------------------------------------|
+ | * DEFAULT is the default region- and segment-name |
+ | |
+ | ** MUMPS is the default file-name |
+ | |
+ | *** May vary by platform |
+ | |
+ | **** -NONULL_SUBSCRIPTS |
+ |-----------------------------------------------------------------------------------------------------|
+ |-AC[CESS_METHOD]=code |BG |- |- |- |- |X |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-AL[LOCATION]=size(blocks) |100 |10 |1,040,187,392(992Mi) |- |- |X |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-BL[OCK_SIZE]=size(bytes) |1024 |512 |65024 |- |- |X |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-C[OLLATION_DEFAULT]=id-number (integer) |0 |0 |255 |- |X |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-D[YNAMIC_SEGMENT]=segment-name (chars) |* |1A |16A/N |- |X |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-EX[TENSION_COUNT]=size (blks) |100 |0 |65535 |- |- |X |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-F[ILE_NAME]=file-name (chars) |** |1A |255A/N |- |- |X |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-G[LOBAL_BUFFER_COUNT]=size (blocks) |1,024 |64 |2,147,483,647 *** |- |- |X |
+ | |*** | | | | | |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-K[EY_SIZE]=size (bytes) |64 |3 |1,019 |- |X |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-L[OCK_SPACE]=size (pages) |40 |10 |65,536 |- |- |X |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-M[UTEX_SLOTS]=integer |1,024 |1,024 |32,768 |- |- |X |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-[NO]INST[_FREEZE_ON_ERROR] |FALSE |- |- |- |X |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-[NO]Q[DBRUNDOWN] |FALSE |- |- |- |X |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-[NO]J[OURNAL]=option-list |-NOJ |- |- |- |X |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-N[ULL_SUBSCRIPTS]=[ALWAYS|NEVER|EXISTING] |NEVER |- |- |- |X |- |
+ | |or ****| | | | | |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-[NO]STDNULLCOLL[=TRUE|FALSE] |FALSE |- |- |- |X |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-R[ECORD_SIZE]=size (bytes) |256 |7 |1,048,576 |- |X |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-R[EGION] region-name (chars) |* |1A |16A/N |X |- |- |
+ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----|
+ |-R[ESERVED_BYTES]=size (bytes) |0 |0 |blocksize |- |- |X |
+ +-----------------------------------------------------------------------------------------------------+
1 Copyright
Copyright
- Copyright 2013
+ Copyright 2014
Fidelity Information Services, Inc. All rights reserved.
@@ -1702,7 +2067,7 @@
**Note**
- This help file is a concise representation of revision V6.1-000 of the
+ This help file is a concise representation of revision V6.2-000 of the
UNIX Administration and Operations Guide. To obtain a copy of the current
revision, go to www.fis-gtm.com and then click on the User Documentation
tab.
diff --git a/sr_port/gdeshow.m b/sr_port/gdeshow.m
index 6eb5651..28e3b86 100644
--- a/sr_port/gdeshow.m
+++ b/sr_port/gdeshow.m
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2001, 2013 Fidelity Information Services, Inc ;
+; Copyright 2001, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -22,10 +22,11 @@ COMMANDS
k tmpreg2,tmpseg2
s BOL="!"
set delim=$select("VMS"=ver:"/",1:"-")
+ ; show NAMES after GBLNAME to avoid potential NAMRANGEORDER errors in case of non-zero collation
i '$l($get(cfile)) d
- . f i="@useio",$s(log:"@uself",1:"") q:'$l(i) u @i d templatec,regionc,segmentc,namec,gblnamec
+ . f i="@useio",$s(log:"@uself",1:"") q:'$l(i) u @i d templatec,regionc,segmentc,gblnamec,namec
e o cfile:(newversion:exc="w !,$ztatus c cfile zgoto $zl:cfilefail") u cfile d
- . d templatec,regionc,segmentc,namec,gblnamec
+ . d templatec,regionc,segmentc,gblnamec,namec
. c cfile
cfilefail:
s BOL=""
@@ -138,6 +139,9 @@ onejnl:
regionc:
n s,q,val,synval,tmpval,type
w !,"DELETE "_delim_"REGION "_defreg
+ ; delete DEFAULT SEGMENT at same time DEFAULT REGION is deleted to avoid potential KEYSIZIS issues when
+ ; playing the GDE SHOW -COMMANDS output in a fresh GDE session (GTM-7954).
+ w !,"DELETE "_delim_"SEGMENT "_defseg
s s=""
f s s=$o(regs(s)) q:'$l(s) d
. w !,"ADD "_delim_"REGION ",s
@@ -221,7 +225,6 @@ MM w ?x(8),$s(segs(s,"DEFER"):"DEFER",1:"NODEFER")
segmentc:
n s,q,val,synval,tmpval,type,am
s s=""
- w !,"DELETE "_delim_"SEGMENT "_defseg
f s s=$o(segs(s)) q:'$l(s) d
. s am=segs(s,"ACCESS_METHOD")
. w !,"ADD "_delim_"SEGMENT ",s
@@ -310,9 +313,6 @@ tmpjnlbd:
w !,BOL
q
templatec:
- ; ---------------------------------------------------------
- ; dump TEMPLATE -REGION section
- ; ---------------------------------------------------------
n q,synval,tmpval,type,cmd,defercnt,defercmd,i,am,s,freq,freqx,val
; compute template values that are most common across regions and store these into tmpreg
s s=""
@@ -346,6 +346,9 @@ templatec:
. . s val=freqx(am,q,freq)
. . s tmpseg(am,q)=val
; use more optimal templates (tmpreg/tmpseg) while generating template commands below
+ ; ---------------------------------------------------------
+ ; dump TEMPLATE -REGION section
+ ; ---------------------------------------------------------
s q=""
s cmd="TEMPLATE "_delim_"REGION ",defercmd="",defercnt=0
f s q=$o(syntab("TEMPLATE","REGION",q)) q:""=q d
@@ -565,10 +568,10 @@ namedisplaycalc:(name)
i namedispmaxlen<namedisplen s namedispmaxlen=namedisplen
q
mapdispcalc:
- n m,gblname,offset,coll,isplusplus,mlen,mtmp,name,mapdisplen,namelen,namedisp
+ n coll,gblname,isplusplus,m,mapdisplen,mlen,mprev,mtmp,name,namedisp,namelen,offset
s m=""
- f s m=$o(map(m)) q:'$zl(m) d
- . i $l(mapreg),(mapreg'=map(m)) q
+ f s mprev=m,m=$o(map(m)) q:'$zl(m) d
+ . i $l(mapreg),(mapreg'=map(m)),('$zl(mprev)!(mapreg'=map(mprev))) q
. s offset=$zfind(m,ZERO,0)
. i offset=0 s mapdisp(m)=$tr(m,")","0") q ; no subscripts case. finish it off first
. s gblname=$ze(m,1,offset-2),coll=+$g(gnams(gblname,"COLLATION")),mlen=$zl(m)
diff --git a/sr_port/gdsblk.h b/sr_port/gdsblk.h
index 3707ed2..6f1ca21 100644
--- a/sr_port/gdsblk.h
+++ b/sr_port/gdsblk.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -93,6 +93,45 @@
}
#endif
+/* The following macro picks up a record from a block using PREC as the pointer to the record and validates
+ * that the record length, NRECLEN, meets base criteria (is not 0 and does not exceed the top of the
+ * block as identified by PTOP) and return NBLKID on the assumption the block is an index block
+ */
+#define GET_AND_CHECK_RECLEN(STATUS, NRECLEN, PREC, PTOP, NBLKID) \
+{ \
+ sm_uc_ptr_t PVAL; \
+ \
+ STATUS = cdb_sc_normal; \
+ GET_USHORT(NRECLEN, &((rec_hdr_ptr_t)PREC)->rsiz); \
+ if (NRECLEN == 0) \
+ STATUS = cdb_sc_badoffset; \
+ else if (PREC + NRECLEN > PTOP) \
+ STATUS = cdb_sc_blklenerr; \
+ else \
+ { \
+ PVAL = PREC + NRECLEN - SIZEOF(block_id); \
+ GET_LONG(NBLKID, PVAL); \
+ } \
+}
+
+/* The following macro picks up a the level from a block using PBLKBASE as the pointer to the header and validates
+ * that the block level, NLEVL, meets base criteria (is not greater than MAX_BT_DEPTH and matches the expected
+ * level as identified by DESIREDLVL)
+ */
+#define GET_AND_CHECK_LEVL(STATUS, NLEVL, DESIREDLVL, PBLKBASE) \
+{ \
+ STATUS = cdb_sc_normal; \
+ NLEVL = ((blk_hdr_ptr_t)PBLKBASE)->levl; \
+ if (MAX_BT_DEPTH < (int)NLEVL) \
+ STATUS = cdb_sc_maxlvl; \
+ else if (ANY_ROOT_LEVL == DESIREDLVL) \
+ { \
+ if (0 == (int)NLEVL) \
+ STATUS = cdb_sc_badlvl; \
+ } else if (DESIREDLVL !=(int)NLEVL) \
+ STATUS = cdb_sc_badlvl; \
+}
+
#if defined(__alpha) && defined(__vms)
# pragma member_alignment save
# pragma nomember_alignment
diff --git a/sr_port/gdsfhead.h b/sr_port/gdsfhead.h
index 810a0eb..e6cbcbf 100644
--- a/sr_port/gdsfhead.h
+++ b/sr_port/gdsfhead.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -1096,6 +1096,7 @@ GBLREF int4 pin_fail_phase2_commit_pidcnt; /* Number of processes in phase2 com
{ \
GBLREF jnlpool_ctl_ptr_t jnlpool_ctl; \
GBLREF boolean_t is_updproc; \
+ GBLREF jnlpool_addrs jnlpool; \
\
unsigned char instfilename_copy[MAX_FN_LEN + 1]; \
sm_uc_ptr_t jnlpool_instfilename; \
@@ -1112,11 +1113,12 @@ GBLREF int4 pin_fail_phase2_commit_pidcnt; /* Number of processes in phase2 com
if (!(SCNDDBNOUPD_CHECK_DONE & jnlpool_validate_check) && SCNDDBNOUPD_CHECK_NEEDED) \
{ \
if (jnlpool_ctl->upd_disabled && !is_updproc) \
- { /* Updates are disabled in this journal pool. Detach from journal pool and issue error. */ \
- assert(NULL != jnlpool.jnlpool_ctl); \
- jnlpool_detach(); \
- assert(NULL == jnlpool.jnlpool_ctl); \
- assert(FALSE == pool_init); \
+ { /* Updates are disabled in this journal pool. Issue error. Do NOT detach from journal pool \
+ * as that would cause us not to honor instance freeze (in case gtm_custom_errors env var is \
+ * non-null) for database reads that this process later does (for example reading a block \
+ * might require us to flush a dirty buffer to disk which should pause if the instance is \
+ * frozen). \
+ */ \
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_SCNDDBNOUPD); \
} \
CSA->jnlpool_validate_check |= SCNDDBNOUPD_CHECK_DONE; \
@@ -1543,6 +1545,8 @@ enum tp_blkmod_type /* used for accounting in cs_data->tp_cdb_sc_blkmod[] */
#define DONOTCOMMIT_GVCST_SEARCH_LEAF_BUFFADR_NOTSYNC (1 << 6) /* Restartable situation encountered in gvcst_search */
#define DONOTCOMMIT_GVCST_SEARCH_BLKTARGET_MISMATCH (1 << 7) /* Restartable situation encountered in gvcst_search */
#define DONOTCOMMIT_REALLOCATE_BITMAP_BMLMOD (1 << 8) /* Restartable situation encountered in reallocate_bitmap */
+#define DONOTCOMMIT_T_WRITE_CSE_DONE (1 << 9) /* Restartable situation encountered in t_write */
+#define DONOTCOMMIT_T_WRITE_CSE_MODE (1 << 10) /* Restartable situation encountered in t_write */
#define TAB_BG_TRC_REC(A,B) B,
enum bg_trc_rec_type
@@ -2238,6 +2242,7 @@ typedef struct sgmnt_addrs_struct
uint4 onln_rlbk_cycle; /* local copy of cnl->onln_rlbk_cycle */
uint4 db_onln_rlbkd_cycle; /* local copy of cnl->db_onln_rlbkd_cycle */
boolean_t dbinit_shm_created; /* TRUE if shared memory for this region was created by this process */
+ boolean_t read_only_fs; /* TRUE if the region is read_only and the header was not updated due to EROFS */
# endif
} sgmnt_addrs;
@@ -2965,6 +2970,7 @@ GBLREF sgmnt_addrs *cs_addrs;
mval temp; \
unsigned char buff[MAX_ZWR_KEY_SZ], *end; \
int len; \
+ mstr opstr; \
\
was_null |= is_null; \
if (mvarg->mvtype & MV_SUBLIT) \
@@ -2976,7 +2982,9 @@ GBLREF sgmnt_addrs *cs_addrs;
/* collation transformation should be done at the server's end for CM regions */ \
assert(dba_cm != REG_ACC_METH(reg)); \
TREF(transform) = FALSE; \
- end = gvsub2str((uchar_ptr_t)mvarg->str.addr, buff, FALSE); \
+ opstr.addr = (char *)buff; \
+ opstr.len = MAX_ZWR_KEY_SZ; \
+ end = gvsub2str((uchar_ptr_t)mvarg->str.addr, &opstr, FALSE); \
TREF(transform) = TRUE; \
temp.mvtype = MV_STR; \
temp.str.addr = (char *)buff; \
diff --git a/sr_port/get_cmd_qlf.c b/sr_port/get_cmd_qlf.c
index fc05f60..44ab8fb 100644
--- a/sr_port/get_cmd_qlf.c
+++ b/sr_port/get_cmd_qlf.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -174,4 +174,10 @@ void get_cmd_qlf(command_qualifier *qualif)
if (CLI_PRESENT == cli_present("DYNAMIC_LITERALS"))
qualif->qlf |= CQ_DYNAMIC_LITERALS;
# endif
+# ifdef UNIX
+ if (CLI_PRESENT == cli_present("EMBED_SOURCE"))
+ qualif->qlf |= CQ_EMBED_SOURCE;
+ else if (cli_negated("EMBED_SOURCE"))
+ qualif->qlf &= ~CQ_EMBED_SOURCE;
+# endif
}
diff --git a/sr_port/get_dlr_zkey.c b/sr_port/get_dlr_zkey.c
index 4d650c0..4792445 100644
--- a/sr_port/get_dlr_zkey.c
+++ b/sr_port/get_dlr_zkey.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -17,6 +17,26 @@ GBLREF io_pair io_curr_device;
void get_dlr_zkey(mval *v)
{
- (io_curr_device.out->disp_ptr->dlr_zkey)(&v->str);
- v->mvtype = MV_STR;
+# ifdef UNIX
+ mstr x;
+ char buff[128], *cp, *cend;
+
+ if (rm == io_curr_device.in->type)
+ {
+ x.len = SIZEOF(buff);
+ x.addr = buff;
+ (io_curr_device.in->disp_ptr->dlr_zkey)(&x);
+ v->mvtype = MV_STR;
+ v->str.addr = cp = x.addr;
+ cend = cp + x.len;
+ for ( ; cp < cend && *cp ; cp++)
+ ;
+ v->str.len = INTCAST(cp - v->str.addr);
+ s2pool(&v->str);
+ } else
+# endif
+ {
+ (io_curr_device.in->disp_ptr->dlr_zkey)(&v->str);
+ v->mvtype = MV_STR;
+ }
}
diff --git a/sr_port/goframes.c b/sr_port/goframes.c
index 74b695d..bc74e75 100644
--- a/sr_port/goframes.c
+++ b/sr_port/goframes.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -36,9 +36,10 @@
GBLREF boolean_t goframes_unwound_trigger;
#endif
+GBLREF mval *alias_retarg;
+GBLREF stack_frame *frame_pointer;
GBLREF boolean_t skip_error_ret;
GBLREF tp_frame *tp_pointer;
-GBLREF stack_frame *frame_pointer;
LITREF mval literal_null;
@@ -60,7 +61,11 @@ void goframes(int4 frames)
if (0 == frames)
{
ret_targ = (mval *)get_ret_targ(NULL);
- if (NULL != ret_targ)
+ /* If alias_retarg is non-NULL, *ret_targ would have been already initialized so no need to set it.
+ * Setting it to literal_null in that case would cause reference counts to not be decremented later
+ * in op_unwind/mdb_condition_handler so it is actually necessary to skip it in that case.
+ */
+ if ((NULL != ret_targ) && (NULL == alias_retarg))
{
*ret_targ = literal_null;
ret_targ->mvtype |= MV_RETARG;
diff --git a/sr_port/gtm_common_defs.h b/sr_port/gtm_common_defs.h
index 14cd3b2..f80d01d 100644
--- a/sr_port/gtm_common_defs.h
+++ b/sr_port/gtm_common_defs.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012, 2013 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -80,10 +80,6 @@
# define DIR_SEPARATOR '/'
#endif
-/* Use the below macros for function declarations and definitions that are part of an API */
-#define _GTM_APIDECL
-#define _GTM_APIDEF
-
/* the LITERAL version of the macro should be used over STRING whenever possible for efficiency reasons */
#define STR_LIT_LEN(LITERAL) (SIZEOF(LITERAL) - 1)
#define LITERAL_AND_LENGTH(LITERAL) (LITERAL), (SIZEOF(LITERAL) - 1)
@@ -110,6 +106,14 @@
#define ROUND_UP(VALUE, MODULUS) (DIVIDE_ROUND_UP(VALUE, MODULUS) * (MODULUS))
#define ROUND_DOWN(VALUE, MODULUS) (DIVIDE_ROUND_DOWN(VALUE, MODULUS) * (MODULUS))
+/* Macros to enable block macros to be used in any context taking a single statement.
+ * See MALLOC_* macros below for examples of use.
+ * Note that if the macro block does a break or continue and expects it to transfer control
+ * to the calling context, these cannot be used.
+ */
+#define MBSTART do
+#define MBEND while (FALSE)
+
/* Macro to copy a source string to a malloced area that is set to the destination pointer.
* Since it is possible that DST might have multiple pointer dereferences in its usage, we
* use a local pointer variable and finally assign it to DST thereby avoiding duplication of
@@ -117,7 +121,7 @@
* There are two macros depending on whether a string or literal is passed.
*/
#define MALLOC_CPY_STR(DST, SRC) \
-{ \
+MBSTART { \
char *mcs_ptr; \
int mcs_len; \
\
@@ -125,10 +129,10 @@
mcs_ptr = malloc(mcs_len); \
memcpy(mcs_ptr, SRC, mcs_len); \
DST = mcs_ptr; \
-}
+} MBEND
#define MALLOC_CPY_LIT(DST, SRC) \
-{ \
+MBSTART { \
char *mcs_ptr; \
int mcs_len; \
\
@@ -136,15 +140,15 @@
mcs_ptr = malloc(mcs_len); \
memcpy(mcs_ptr, SRC, mcs_len); \
DST = mcs_ptr; \
-}
+} MBEND
#define MALLOC_INIT(DST, SIZ) \
-{ \
+MBSTART { \
void *lcl_ptr; \
\
lcl_ptr = malloc(SIZ); \
memset(lcl_ptr, 0, SIZ); \
DST = lcl_ptr; \
-}
+} MBEND
#endif /* GTM_COMMON_DEFS_H */
diff --git a/sr_port/gtm_ctype.h b/sr_port/gtm_ctype.h
index 55a5924..eaff3f8 100644
--- a/sr_port/gtm_ctype.h
+++ b/sr_port/gtm_ctype.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -106,15 +106,18 @@
#define ISXDIGIT isxdigit
#define ISXDIGIT_ASCII(CH) (IS_ASCII(CH) && ISXDIGIT(CH))
+LITREF unsigned char lower_to_upper_table[];
+LITREF unsigned char upper_to_lower_table[];
+
#ifdef TOLOWER
#undef TOLOWER
-#endif
-#define TOLOWER tolower
+#endif /* this macro works only on lower-case ASCII characters and leaves others as-is */
+#define TOLOWER(C) upper_to_lower_table[(unsigned char)C]
#ifdef TOUPPER
#undef TOUPPER
-#endif
-#define TOUPPER toupper
+#endif /* this macro works only on upper-case ASCII characters and leaves others as-is */
+#define TOUPPER(C) lower_to_upper_table[(unsigned char)C]
#if defined(__osf__) && defined(__alpha)
diff --git a/sr_port/gtm_env_init.c b/sr_port/gtm_env_init.c
index 013c8f7..acde640 100644
--- a/sr_port/gtm_env_init.c
+++ b/sr_port/gtm_env_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2004, 2013 Fidelity Information Services, Inc *
+ * Copyright 2004, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -79,7 +79,6 @@ GBLREF block_id gtm_tp_allocation_clue; /* block# hint to start allocation for c
GBLREF boolean_t gtm_stdxkill; /* Use M Standard exclusive kill instead of historical GTM */
GBLREF boolean_t ztrap_new; /* Each time $ZTRAP is set it is automatically NEW'd */
GBLREF size_t gtm_max_storalloc; /* Used for testing: creates an allocation barrier */
-GBLREF boolean_t ipv4_only; /* If TRUE, only use AF_INET. */
void gtm_env_init(void)
{
@@ -113,12 +112,30 @@ void gtm_env_init(void)
val.addr = GTM_BOOLEAN;
val.len = SIZEOF(GTM_BOOLEAN) - 1;
TREF(gtm_fullbool) = trans_numeric(&val, &is_defined, TRUE);
- /* gtm_boolean environment/logical */
+ switch (TREF(gtm_fullbool))
+ {
+ case GTM_BOOL: /* original GT.M short-circuit Boolean evaluation with naked maintenance */
+ case FULL_BOOL: /* standard behavior - evaluate everything with a side effect */
+ case FULL_BOOL_WARN: /* like FULL_BOOL but give compiler warnings when it makes a difference */
+ break;
+ default:
+ TREF(gtm_fullbool) = GTM_BOOL;
+ }
+ /* gtm_side_effects environment/logical */
val.addr = GTM_SIDE_EFFECT;
val.len = SIZEOF(GTM_SIDE_EFFECT) - 1;
TREF(side_effect_handling) = trans_numeric(&val, &is_defined, TRUE);
- if (!is_defined) /* default to original behavior */
- TREF(side_effect_handling) = OLD_SE;
+ switch (TREF(side_effect_handling))
+ {
+ case OLD_SE: /* ignore side effect implications */
+ case STD_SE: /* reorder argument processing for left-to-right side effects */
+ case SE_WARN: /* like STD but give compiler warnings when it makes a difference */
+ break;
+ default:
+ TREF(side_effect_handling) = OLD_SE; /* default is: ignore side effect implications */
+ }
+ if ((OLD_SE != TREF(side_effect_handling)) && (GTM_BOOL == TREF(gtm_fullbool))) /* side effect implies full bool */
+ TREF(gtm_fullbool) = FULL_BOOL;
/* NOUNDEF environment/logical */
val.addr = GTM_NOUNDEF;
val.len = SIZEOF(GTM_NOUNDEF) - 1;
@@ -317,12 +334,6 @@ void gtm_env_init(void)
val.addr = GTM_MAX_STORALLOC;
val.len = SIZEOF(GTM_MAX_STORALLOC) - 1;
gtm_max_storalloc = trans_numeric(&val, &is_defined, TRUE);
-# ifdef UNIX
- /* See if gtm_ipv4_only is set */
- val.addr = GTM_IPV4_ONLY;
- val.len = SIZEOF(GTM_IPV4_ONLY) - 1;
- ipv4_only = logical_truth_value(&val, FALSE, NULL);
-# endif
/* Platform specific initializations */
gtm_env_init_sp();
}
diff --git a/sr_port/gtm_fetch.c b/sr_port/gtm_fetch.c
index e057ddd..35b69a2 100644
--- a/sr_port/gtm_fetch.c
+++ b/sr_port/gtm_fetch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2012 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,14 +19,16 @@
#include "op.h"
#include "lv_val.h"
-#ifdef DEBUG /* all of below is needed by the gv_target/cs_addrs assert */
-#include "gdsroot.h"
+#ifdef DEBUG
+#include "gdsroot.h" /* all of below until gdsfhead.h is needed by the gv_target/cs_addrs assert */
#include "gdskill.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
+#include "mvalconv.h"
+#include "alias.h"
#endif
GBLREF stack_frame *frame_pointer;
@@ -45,11 +47,13 @@ void gtm_fetch(unsigned int indxarg, ...)
#error unsupported platform
#endif
{
- va_list var;
- unsigned int indx;
- unsigned int cnt;
- stack_frame *fp;
ht_ent_mname **htepp;
+ stack_frame *fp;
+ unsigned int cnt, indx;
+ va_list var;
+# ifdef DEBUG
+ static int als_lvval_gc_frequency, fetch_invocation;
+# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -60,9 +64,26 @@ void gtm_fetch(unsigned int indxarg, ...)
* compile-time error.
*/
assert(!TREF(in_zwrite)); /* Verify in_zwrite was not left on */
+ DEBUG_ONLY(SET_ACTIVE_LV(NULL, TRUE, actlv_gtm_fetch);)
+# ifdef DEBUG
+ if (0 == als_lvval_gc_frequency)
+ {
+ mval tmpmval, *random_mval = &tmpmval;
+
+ op_fnrandom(1024, random_mval);
+ als_lvval_gc_frequency = 8 + MV_FORCE_INT(random_mval);
+ }
+ if (++fetch_invocation == als_lvval_gc_frequency)
+ {
+ als_lvval_gc();
+ fetch_invocation = 0;
+ if (als_lvval_gc_frequency < 1024)
+ als_lvval_gc_frequency *= 2;
+ }
+# endif
VAR_START(var, indxarg);
- VMS_ONLY(va_count(cnt);)
- UNIX_ONLY(cnt = cnt_arg;) /* need to preserve stack copy on i386 */
+ VMS_ONLY(va_count(cnt));
+ UNIX_ONLY(cnt = cnt_arg); /* need to preserve stack copy on i386 */
fp = frame_pointer;
if (0 < cnt)
{ /* All generated code comes here to verify instantiation
diff --git a/sr_port/gtm_limits.h b/sr_port/gtm_limits.h
index f8fb9b9..cb50da5 100644
--- a/sr_port/gtm_limits.h
+++ b/sr_port/gtm_limits.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2002, 2012 Fidelity Information Services, Inc *
+ * Copyright 2002, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,6 +40,17 @@
#endif
/* Now define our version which includes space for a terminating NULL byte */
#define GTM_PATH_MAX PATH_MAX + 1
+/* The maximum path to the GT.M distribution is complicated by the paths underneath $gtm_dist.
+ * At the top level, there is libgtmshr.{so,sl,dll} which is roughly 12 characters plus 1 for the
+ * slash. The path length of gtmsecshrdir/gtmsecshr doesn't come into play because
+ * $gtm_dist/gtmsecshr will change directory to $gtm_dist/gtmsecshrdir (13 characters including the
+ * leading slash) and then exec gtmsecshr, avoiding the maximum path issue. Going to "UTF-8" mode adds
+ * another 5 characters ("utf8/") to the path name. The encryption library path,
+ * $gtm_dist/plubin/libgtmcrypt.so is a symlink to some much longer named files which the code will
+ * realpath() before dlopen()ing. As it stands, the longest path is 47 characters (including the "UTF-8"
+ * directory. Thus PATH_MAX - 50 characters should be a good compromise for today and future expansion.
+ * Just in case, the build script verify that nothing past $gtm_dist is more than 50 characters long. */
+#define GTM_DIST_PATH_MAX GTM_PATH_MAX - 50
#if defined(LLONG_MAX) /* C99 and others */
#define GTM_INT64_MIN LLONG_MIN
diff --git a/sr_port/gtm_newintrinsic.c b/sr_port/gtm_newintrinsic.c
index db9cb1e..9c92aae 100644
--- a/sr_port/gtm_newintrinsic.c
+++ b/sr_port/gtm_newintrinsic.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -25,10 +25,14 @@ GBLREF stack_frame *frame_pointer;
GBLREF tp_frame *tp_pointer;
GBLREF symval *curr_symval;
GBLREF uint4 dollar_tlevel;
+GBLREF mval dollar_etrap;
#ifdef GTM_TRIGGER
GBLREF mval dollar_ztwormhole;
#endif
+error_def(ERR_STACKCRIT);
+error_def(ERR_STACKOFLOW);
+
/* Note this module follows the basic pattern of op_newvar which handles the same
function except for local vars instead of intrinsic vars. */
void gtm_newintrinsic(mval *intrinsic)
@@ -40,9 +44,6 @@ void gtm_newintrinsic(mval *intrinsic)
int indx;
int4 shift_size;
- error_def(ERR_STACKOFLOW);
- error_def(ERR_STACKCRIT);
-
assert(intrinsic);
if (frame_pointer->type & SFT_COUNT)
{ /* Current (youngest) frame is NOT an indirect frame.
@@ -84,10 +85,10 @@ void gtm_newintrinsic(mval *intrinsic)
if (msp <= stacktop)
{
msp = old_sp;
- rts_error(VARLSTCNT(1) ERR_STACKOFLOW);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKOFLOW);
}
else
- rts_error(VARLSTCNT(1) ERR_STACKCRIT);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKCRIT);
}
/* Ready, set, shift the younger indirect frames to make room for mv_stent */
memmove(msp, old_sp, top - (unsigned char *)old_sp);
@@ -145,15 +146,11 @@ void gtm_newintrinsic(mval *intrinsic)
mv_st_ent->mv_st_cont.mvs_msav.v = *intrinsic;
mv_st_ent->mv_st_cont.mvs_msav.addr = intrinsic;
}
- /* New the intrinsic var's current value if not $ZTWORMHOLE */
-# ifdef GTM_TRIGGER
- if (&dollar_ztwormhole != intrinsic)
+ /* Clear the intrinsic var's current value if not $ZTWORMHOLE or $ETRAP */
+ if ((&dollar_etrap != intrinsic) GTMTRIG_ONLY(&& (&dollar_ztwormhole != intrinsic)))
{
-# endif
intrinsic->mvtype = MV_STR;
intrinsic->str.len = 0;
-# ifdef GTM_TRIGGER
}
-# endif
return;
}
diff --git a/sr_port/gtm_rename.h b/sr_port/gtm_rename.h
index 65d7935..f99ce86 100644
--- a/sr_port/gtm_rename.h
+++ b/sr_port/gtm_rename.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -28,6 +28,5 @@ uint4 gtm_rename(char *org_fn, int org_fn_len, char *rename_fn, int rename_len,
uint4 prepare_unique_name(char *org_fn, int org_fn_len, char *prefix, char *suffix, char *rename_fn, int *rename_fn_len,
jnl_tm_t now, uint4 *ustatus);
uint4 append_time_stamp(char *fn, int *fn_len, jnl_tm_t now);
-void cre_jnl_file_intrpt_rename(int fn_len, sm_uc_ptr_t fn);
#endif
diff --git a/sr_port/gtm_savetraps.c b/sr_port/gtm_savetraps.c
index 2440bde..44da53e 100644
--- a/sr_port/gtm_savetraps.c
+++ b/sr_port/gtm_savetraps.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,8 +13,9 @@
#include "gtm_savetraps.h"
#include "gtm_newintrinsic.h"
-GBLREF mval dollar_ztrap;
-GBLREF mval dollar_etrap;
+GBLREF mval dollar_ztrap;
+GBLREF mval dollar_etrap;
+GBLREF boolean_t ztrap_explicit_null;
/* Routine called when we need to save the current Xtrap (etrap or ztrap) but
don't know which to save.
@@ -23,7 +24,7 @@ void gtm_savetraps(void)
{
mval *intrinsic;
- if (dollar_ztrap.str.len)
+ if (dollar_ztrap.str.len || ztrap_explicit_null)
intrinsic = &dollar_ztrap;
else
intrinsic = &dollar_etrap;
diff --git a/sr_port/gtm_threadgbl_defs.h b/sr_port/gtm_threadgbl_defs.h
index cacdd7b..4bb2098 100644
--- a/sr_port/gtm_threadgbl_defs.h
+++ b/sr_port/gtm_threadgbl_defs.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -59,6 +59,7 @@ THREADGBLDEF(indirection_mval, mval) /* used for parsing subscripted indire
THREADGBLDEF(last_source_column, short int) /* parser tracker */
THREADGBLDEF(pos_in_chain, triple) /* anchor used to restart after a parsing error */
THREADGBLDEF(s2n_intlit, boolean_t) /* type info from s2n for advancewindow */
+THREADGBLDEF(routine_source_offset, uint4) /* offset of M source within literal text pool */
THREADGBLDEF(saw_side_effect, boolean_t) /* need side effect handling other than naked */
THREADGBLDEF(shift_side_effects, int) /* flag shifting of side-effects ahead of boolean
* evalation */
@@ -222,6 +223,7 @@ THREADGBLFPTR(gtm_env_xlate_entry, int, ()) /* gtm_env_xlate() function point
THREADGBLDEF(gtm_environment_init, boolean_t) /* indicates GT.M development environment rather
* than a production environment */
THREADGBLFPTR(gtm_sigusr1_handler, void, (void)) /* SIGUSR1 signal handler function ptr */
+THREADGBLDEF(gtm_linktmpdir, mstr) /* Directory to use for relinkctl files */
THREADGBLDEF(gtm_trctbl_cur, trctbl_entry *) /* Current gtm trace table entry */
THREADGBLDEF(gtm_trctbl_end, trctbl_entry *) /* End of gtm trace table (last entry + 1) */
THREADGBLDEF(gtm_trctbl_groups, unsigned int) /* Trace group mask (max 31 groups) */
@@ -232,6 +234,9 @@ THREADGBLDEF(gtmprompt, mstr) /* mstr pointing to prombuf containing the G
THREADGBLDEF(gtmsecshr_comkey, unsigned int) /* Hashed version key for gtmsecshr communications
* eliminates cross-version issues */
THREADGBLDEF(in_zwrite, boolean_t) /* ZWrite is active */
+THREADGBLDEF(lab_lnr, lnr_tabent **) /* Passes address from op_rhd_ext to op_extcall etc.
+ * Points into either lab_proxy or linkage table
+ */
THREADGBLDEF(lab_proxy, lab_tabent_proxy) /* Placeholder storing lab_ln_ptr offset / lnr_adr
* pointer and has_parms value, so they are
* contiguous in memory */
@@ -255,6 +260,10 @@ THREADGBLDEF(mprof_reclaim_cnt, int) /* Amount of mem to reclaim after unw_
THREADGBLDEF(mprof_stack_curr_frame, mprof_stack_frame *) /* Pointer to the last frame on the mprof stack */
THREADGBLDEF(mprof_stack_next_frame, mprof_stack_frame *) /* Pointer to the next frame to be put on the
* mprof stack */
+#ifdef USHBIN_SUPPORTED
+THREADGBLDEF(open_relinkctl_list, open_relinkctl_sgm *) /* Anchor for open relinkctl list; similar to
+ * open_shlib_root */
+#endif
#ifdef UNIX
THREADGBLDEF(open_shlib_root, open_shlib *) /* Anchor for open shared library list */
#endif
@@ -268,7 +277,13 @@ THREADGBLDEF(pipefifo_interrupt, int) /* count of number of times a pipe or
* interrupted */
#endif
THREADGBLDEF(prof_fp, mprof_stack_frame *) /* Stack frame that mprof currently operates on */
+#ifdef USHBIN_SUPPORTED
+THREADGBLDEF(recent_zhist, zro_hist *) /* Saved history from last zro_search */
+#endif
THREADGBLDEF(relink_allowed, int) /* Non-zero if recursive relink permitted */
+THREADGBLDEF(set_zroutines_cycle, uint4) /* Informs us if we changed $ZROUTINES between
+ * linking a routine and invoking it
+ */
THREADGBLDEF(trans_code_pop, mval *) /* trans_code holder for $ZTRAP popping */
THREADGBLDEF(view_ydirt_str, char *) /* op_view working storage for ydir* ops */
THREADGBLDEF(view_ydirt_str_len, int4) /* Part of op_view working storage for ydir* ops */
@@ -282,6 +297,7 @@ THREADGBLDEF(zsearch_dir2, lv_val *) /* UNIX $zsearch() directory 2 */
#endif
THREADGBLDEF(poll_fds_buffer, char *) /* Buffer for poll() argument */
THREADGBLDEF(poll_fds_buffer_size, size_t) /* Current allocated size of poll_fds_buffer */
+THREADGBLDEF(socket_handle_counter, int) /* Counter for generated socket handles */
/* Larger structures and char strings */
THREADGBLAR1DEF(director_string, char, SIZEOF(mident_fixed)) /* Buffer for director_ident */
@@ -294,6 +310,7 @@ THREADGBLDEF(lcl_coll_xform_buff, char *) /* This buffer is for local collat
* a transformation routine must not call another,
* or itself. This kind of nesting would cause
* overwriting of the buffer */
+THREADGBLDEF(protmem_ba, mstr) /* Protected buffer */
#ifdef UNIX
THREADGBLAR1DEF(parm_ary, char *, MAX_PARMS) /* Parameter strings buffer */
THREADGBLAR1DEF(parm_ary_len, int, MAX_PARMS) /* Array element allocation length */
@@ -384,7 +401,12 @@ THREADGBLDEF(gvt_triggers_read_this_tn, boolean_t) /* if non-zero, indicates
* useful to invalidate all those triggers in case
* of a transaction restart or rollback.
*/
-THREADGBLDEF(in_op_fntext, boolean_t) /* Denote the trigger was processed in $Text() */
+THREADGBLDEF(op_fntext_tlevel, uint4) /* Non-zero implies $TEXT argument is a trigger
+ * routine.
+ * If non-zero, this is 1 + dollar_tlevel at
+ * the time of the call to "get_src_line" in
+ * op_fntext.c. Later used by fntext_ch.c.
+ */
#endif
/* Debug values */
@@ -407,4 +429,10 @@ THREADGBLDEF(gtm_gvundef_fatal, boolean_t) /* core and die intended for test
THREADGBLDEF(gtm_dirtree_collhdr_always, boolean_t) /* Initialize 4-byte collation header in directory tree always.
* Used by tests that are sensitive to DT leaf block layout.
*/
+THREADGBLDEF(activelv_cycle, int) /* # of times SET_ACTIVE_LV macro has been invoked */
+THREADGBLDEF(activelv_index, int) /* == (activelv_cycle % ACTIVELV_DBG_ARRAY_SIZE_DEF) */
+THREADGBLDEF(activelv_dbg_array, activelv_dbg_t *) /* pointer to array holding trace details for
+ * ACTIVELV_DBG_ARRAY_SIZE_DEF most recent
+ * invocations of SET_ACTIVE_LV */
+THREADGBLDEF(cli_get_str_max_len, uint4)
#endif
diff --git a/sr_port/gtm_threadgbl_deftypes.c b/sr_port/gtm_threadgbl_deftypes.c
index b4ccd1e..1791cd3 100644
--- a/sr_port/gtm_threadgbl_deftypes.c
+++ b/sr_port/gtm_threadgbl_deftypes.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -142,6 +142,11 @@
# include "gtm_trigger.h"
#endif
+#ifdef USHBIN_SUPPORTED
+# include "relinkctl.h"
+# include "zhist.h"
+#endif
+
/* This module's purpose is to generate gtm_threadgbl_deftypes.h for a given platform. This header file
* contains all the type and offset informatin needed for the TREF macro in gtm_threadgbl.h to access
* any field in the global structure without having to have all the types known in every module. Only the
diff --git a/sr_port/gtm_threadgbl_init.c b/sr_port/gtm_threadgbl_init.c
index 2449928..5b4486c 100644
--- a/sr_port/gtm_threadgbl_init.c
+++ b/sr_port/gtm_threadgbl_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -152,6 +152,11 @@
# include "gtm_trigger.h"
#endif
+#ifdef USHBIN_SUPPORTED
+# include "relinkctl.h"
+# include "zhist.h"
+#endif
+
#include "gtm_threadgbl_init.h"
#define DEFAULT_PROMPT "GTM>"
diff --git a/sr_port/gtm_un.h b/sr_port/gtm_un.h
index 36eb615..fa13715 100644
--- a/sr_port/gtm_un.h
+++ b/sr_port/gtm_un.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -15,5 +15,7 @@
#ifndef VMS
#include <sys/un.h>
#endif
-
+#ifdef __hpux
+#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path))
+#endif
#endif
diff --git a/sr_port/gtmimagename.h b/sr_port/gtmimagename.h
index f13b5b0..72cdaaf 100644
--- a/sr_port/gtmimagename.h
+++ b/sr_port/gtmimagename.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -34,10 +34,10 @@ GBLREF boolean_t run_time; /* needed by IS_MCODE_RUNNING macro */
#define IS_MCODE_RUNNING (run_time)
#define IS_DSE_IMAGE (DSE_IMAGE == image_type)
+#define IS_GTCM_SERVER_IMAGE (GTCM_SERVER_IMAGE == image_type)
#define IS_GTCM_GNP_SERVER_IMAGE (GTCM_GNP_SERVER_IMAGE == image_type)
#define IS_GTMSECSHR_IMAGE (GTMSECSHR_IMAGE == image_type)
#define IS_GTM_IMAGE IS_MUMPS_IMAGE
-#define IS_GTM_SVC_DAL_IMAGE (GTM_SVC_DAL_IMAGE == image_type)
#define IS_LKE_IMAGE (LKE_IMAGE == image_type)
#define IS_MUMPS_IMAGE (GTM_IMAGE == image_type)
#define IS_MUPIP_IMAGE (MUPIP_IMAGE == image_type)
diff --git a/sr_port/gtmimagetable.h b/sr_port/gtmimagetable.h
index 1554b81..271b114 100644
--- a/sr_port/gtmimagetable.h
+++ b/sr_port/gtmimagetable.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,4 +21,3 @@ IMAGE_TABLE_ENTRY (GTMSECSHR_IMAGE, "GTMSECSHR")
IMAGE_TABLE_ENTRY (GTCM_SERVER_IMAGE, "GTCM_SERVER")
IMAGE_TABLE_ENTRY (GTCM_GNP_SERVER_IMAGE, "GTCM_GNP_SERVER")
IMAGE_TABLE_ENTRY (DBCERTIFY_IMAGE, "DBCERTIFY")
-IMAGE_TABLE_ENTRY (GTM_SVC_DAL_IMAGE, "GTM_SVC_DAL")
diff --git a/sr_port/gtmrecv_helpers_init.c b/sr_port/gtmrecv_helpers_init.c
index 88d806e..fd194cf 100644
--- a/sr_port/gtmrecv_helpers_init.c
+++ b/sr_port/gtmrecv_helpers_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2005, 2013 Fidelity Information Services, Inc.*
+ * Copyright 2005, 2014 Fidelity Information Services, Inc.*
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -43,9 +43,10 @@
#include "eintr_wrappers.h"
#include "memcoherency.h"
#include "getjobnum.h"
+#include "gtmimagename.h"
#define UPDHELPER_CMD_MAXLEN 1024
-#define UPDHELPER_CMD "$gtm_dist/mupip"
+#define UPDHELPER_CMD "%s/mupip"
#define UPDHELPER_CMD_FILE "mupip"
#define UPDHELPER_CMD_ARG1 "replicate"
#define UPDHELPER_CMD_ARG2 "-updhelper"
@@ -57,9 +58,13 @@
/* U for update process, R for receiver, S for source, H for helper */
GBLREF recvpool_addrs recvpool;
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
GBLREF FILE *gtmrecv_log_fp;
GBLREF uint4 process_id;
+LITREF gtmImageName gtmImageNames[];
+error_def(ERR_GTMDISTUNVERIF);
error_def(ERR_LOGTOOLONG);
error_def(ERR_RECVPOOLSETUP);
error_def(ERR_TEXT);
@@ -68,9 +73,9 @@ static int helper_init(upd_helper_entry_ptr_t helper, recvpool_user helper_type)
{
int save_errno, save_shutdown;
char helper_cmd[UPDHELPER_CMD_MAXLEN];
+ int helper_cmd_len;
int status;
int4 i4status;
- mstr helper_log_cmd, helper_trans_cmd;
upd_helper_ctl_ptr_t upd_helper_ctl;
#ifdef UNIX
pid_t helper_pid, waitpid_res;
@@ -85,7 +90,10 @@ static int helper_init(upd_helper_entry_ptr_t helper, recvpool_user helper_type)
save_shutdown = helper->helper_shutdown;
helper->helper_shutdown = NO_SHUTDOWN;
#ifdef UNIX
- FORK(helper_pid); /* BYPASSOK: we exec immediately, no FORK_CLEAN needed */
+ if (!gtm_dist_ok_to_use)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, STRLEN(gtm_dist), gtm_dist,
+ gtmImageNames[image_type].imageNameLen, gtmImageNames[image_type].imageName);
+ FORK(helper_pid);
if (0 > helper_pid)
{
save_errno = errno;
@@ -99,21 +107,15 @@ static int helper_init(upd_helper_entry_ptr_t helper, recvpool_user helper_type)
{ /* helper */
getjobnum();
helper->helper_pid_prev = process_id; /* identify owner of slot */
- helper_log_cmd.len = STR_LIT_LEN(UPDHELPER_CMD);
- helper_log_cmd.addr = UPDHELPER_CMD;
- if (SS_NORMAL != (i4status = TRANS_LOG_NAME(&helper_log_cmd, &helper_trans_cmd, helper_cmd, SIZEOF(helper_cmd),
- dont_sendmsg_on_log2long)))
+ helper_cmd_len = SNPRINTF(helper_cmd, UPDHELPER_CMD_MAXLEN, UPDHELPER_CMD, gtm_dist);
+ if(-1 == helper_cmd_len)
{
helper->helper_shutdown = save_shutdown;
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2,
LEN_AND_LIT("Could not find path of Helper Process. Check value of $gtm_dist"));
- if (SS_LOG2LONG == i4status)
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3,
- LEN_AND_LIT(UPDHELPER_CMD), SIZEOF(helper_cmd) - 1);
repl_errno = EREPL_UPDSTART_BADPATH;
return UPDPROC_START_ERR;
}
- helper_cmd[helper_trans_cmd.len] = '\0';
if (-1 == EXECL(helper_cmd, helper_cmd, UPDHELPER_CMD_ARG1, UPDHELPER_CMD_ARG2,
(UPD_HELPER_READER == helper_type) ? UPDHELPER_READER_CMD_ARG3 : UPDHELPER_WRITER_CMD_ARG3, NULL))
{
@@ -192,8 +194,7 @@ int gtmrecv_helpers_init(int n_readers, int n_writers)
{
for (; 0 != helper->helper_pid && helper < helper_top; helper++) /* find next vacant slot */
;
- if (helper == helper_top)
- GTMASSERT;
+ assertpro(helper != helper_top);
status = helper_init(helper, ((reader_count + error_count) < n_readers) ? UPD_HELPER_READER : UPD_HELPER_WRITER);
if (UPDPROC_STARTED == status)
{
diff --git a/sr_port/gtmrecv_upd_proc_init.c b/sr_port/gtmrecv_upd_proc_init.c
index 4e14fde..0d84541 100644
--- a/sr_port/gtmrecv_upd_proc_init.c
+++ b/sr_port/gtmrecv_upd_proc_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc.*
+ * Copyright 2001, 2014 Fidelity Information Services, Inc.*
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -44,9 +44,10 @@
#include "trans_log_name.h"
#include "repl_log.h"
#include "eintr_wrappers.h"
+#include "gtmimagename.h"
#define UPDPROC_CMD_MAXLEN 1024
-#define UPDPROC_CMD "$gtm_dist/mupip"
+#define UPDPROC_CMD "%s/mupip"
#define UPDPROC_CMD_FILE "mupip"
#define UPDPROC_CMD_ARG1 "replicate"
#define UPDPROC_CMD_ARG2 "-updateproc"
@@ -55,10 +56,14 @@
GBLREF recvpool_addrs recvpool;
GBLREF int recvpool_shmid;
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
GBLREF int gtmrecv_log_fd;
GBLREF FILE *gtmrecv_log_fp;
GBLREF int updproc_log_fd;
+LITREF gtmImageName gtmImageNames[];
+error_def(ERR_GTMDISTUNVERIF);
error_def(ERR_LOGTOOLONG);
error_def(ERR_RECVPOOLSETUP);
error_def(ERR_REPLINFO);
@@ -68,8 +73,8 @@ int gtmrecv_upd_proc_init(boolean_t fresh_start)
{
/* Update Process initialization */
- mstr upd_proc_log_cmd, upd_proc_trans_cmd;
char upd_proc_cmd[UPDPROC_CMD_MAXLEN];
+ int upd_proc_cmd_len;
int status, save_errno;
int upd_status, save_upd_status;
#ifdef UNIX
@@ -105,7 +110,10 @@ int gtmrecv_upd_proc_init(boolean_t fresh_start)
recvpool.upd_proc_local->upd_proc_shutdown = NO_SHUTDOWN;
#ifdef UNIX
- FORK(upd_pid); /* BYPASSOK: we exec immediately, no FORK_CLEAN needed */
+ if (!gtm_dist_ok_to_use)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, STRLEN(gtm_dist), gtm_dist,
+ gtmImageNames[image_type].imageNameLen, gtmImageNames[image_type].imageName);
+ FORK(upd_pid);
if (0 > upd_pid)
{
recvpool.upd_proc_local->upd_proc_shutdown = save_upd_status;
@@ -117,21 +125,14 @@ int gtmrecv_upd_proc_init(boolean_t fresh_start)
if (0 == upd_pid)
{
/* Update Process */
- upd_proc_log_cmd.len = SIZEOF(UPDPROC_CMD) - 1;
- upd_proc_log_cmd.addr = UPDPROC_CMD;
- status = TRANS_LOG_NAME(&upd_proc_log_cmd, &upd_proc_trans_cmd, upd_proc_cmd, SIZEOF(upd_proc_cmd),
- dont_sendmsg_on_log2long);
- if (status != SS_NORMAL)
+ upd_proc_cmd_len = SNPRINTF(upd_proc_cmd, UPDPROC_CMD_MAXLEN, UPDPROC_CMD, gtm_dist);
+ if (-1 == upd_proc_cmd_len)
{
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2,
RTS_ERROR_LITERAL("Could not find path of Update Process. Check value of $gtm_dist"));
- if (SS_LOG2LONG == status)
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5)
- ERR_LOGTOOLONG, 3, LEN_AND_LIT(UPDPROC_CMD), SIZEOF(upd_proc_cmd) - 1);
repl_errno = EREPL_UPDSTART_BADPATH;
return(UPDPROC_START_ERR);
}
- upd_proc_cmd[upd_proc_trans_cmd.len] = '\0';
if (EXECL(upd_proc_cmd, upd_proc_cmd, UPDPROC_CMD_ARG1, UPDPROC_CMD_ARG2, NULL) < 0)
{
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2,
diff --git a/sr_port/gtmsource_ctl_init.c b/sr_port/gtmsource_ctl_init.c
index 45ffded..28db11b 100644
--- a/sr_port/gtmsource_ctl_init.c
+++ b/sr_port/gtmsource_ctl_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -255,9 +255,10 @@ int repl_ctl_create(repl_ctl_element **ctl, gd_region *reg, int jnl_fn_len, char
if (!was_crit)
rel_crit(reg);
if (SS_NORMAL != jpc->status)
- rts_error(VARLSTCNT(7) jnl_status, 4, JNL_LEN_STR(csd), DB_LEN_STR(reg), jpc->status);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(7) jnl_status, 4, JNL_LEN_STR(csd),
+ DB_LEN_STR(reg), jpc->status);
else
- rts_error(VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(csd), DB_LEN_STR(reg));
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(csd), DB_LEN_STR(reg));
} else
{
tmp_ctl->jnl_fn_len = csd->jnl_file_len;
@@ -315,9 +316,10 @@ int repl_ctl_create(repl_ctl_element **ctl, gd_region *reg, int jnl_fn_len, char
tmp_jfh = NULL;
tmp_jfh_base = NULL;
if (SS_NORMAL != status)
- rts_error(VARLSTCNT(7) ERR_JNLFILRDOPN, 4, lcl_jnl_fn_len, lcl_jnl_fn, DB_LEN_STR(reg), status);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_JNLFILRDOPN, 4, lcl_jnl_fn_len,
+ lcl_jnl_fn, DB_LEN_STR(reg), status);
else
- rts_error(VARLSTCNT(6) ERR_JNLNOREPL, 4, lcl_jnl_fn_len, lcl_jnl_fn, DB_LEN_STR(reg));
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_JNLNOREPL, 4, lcl_jnl_fn_len, lcl_jnl_fn, DB_LEN_STR(reg));
}
assert(SS_NORMAL == status); /* so jnl_fs_block_size is guaranteed to have been initialized */
tmp_ctl->repl_buff = repl_buff_create(tmp_jfh->alignsize, jnl_fs_block_size);
@@ -331,7 +333,7 @@ int repl_ctl_create(repl_ctl_element **ctl, gd_region *reg, int jnl_fn_len, char
if (tmp_jfh->is_encrypted)
{
ASSERT_ENCRYPTION_INITIALIZED; /* should be done in db_init (gtmsource() -> gvcst_init() -> db_init()) */
- GTMCRYPT_GETKEY(csa, tmp_jfh->encryption_hash, tmp_ctl->encr_key_handle, gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(csa, tmp_jfh->encryption_hash, tmp_ctl->encr_key_handle, gtmcrypt_errno);
if (0 != gtmcrypt_errno)
GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, rts_error, tmp_ctl->jnl_fn_len, tmp_ctl->jnl_fn);
}
@@ -402,8 +404,8 @@ int gtmsource_ctl_init(void)
prev_ctl = tmp_ctl;
}
}
- if (NULL == repl_ctl_list->next) /* No replicated region */
- GTMASSERT;
+ /* This function should never be invoked unless there is at least one replicated region. */
+ assertpro(NULL != repl_ctl_list->next);
return (SS_NORMAL);
}
diff --git a/sr_port/gv_rundown.c b/sr_port/gv_rundown.c
index acaf5f5..c80e4ef 100644
--- a/sr_port/gv_rundown.c
+++ b/sr_port/gv_rundown.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -52,9 +52,6 @@
#include "rc_cpt_ops.h"
#include "gv_rundown.h"
#include "targ_alloc.h"
-#ifdef GTM_CRYPT
-#include "gtmcrypt.h"
-#endif
#if defined(DEBUG) && defined(UNIX)
#include "anticipatory_freeze.h"
#endif
@@ -107,7 +104,8 @@ void gv_rundown(void)
* region->open is TRUE although cs_addrs is NULL.
*/
# if defined(DEBUG) && defined(UNIX)
- if (is_jnlpool_creator && ANTICIPATORY_FREEZE_AVAILABLE && TREF(gtm_test_fake_enospc))
+ if (is_jnlpool_creator
+ && INST_FREEZE_ON_NOSPC_ENABLED(REG2CSA(r_local)) && TREF(gtm_test_fake_enospc))
{ /* Clear ENOSPC faking now that we are running down */
csa = REG2CSA(r_local);
if (csa->nl->fake_db_enospc || csa->nl->fake_jnl_enospc)
@@ -199,7 +197,6 @@ void gv_rundown(void)
rc_close_section();
gv_cur_region = r_save; /* Restore value for dumps but this region is now closed and is otherwise defunct */
cs_addrs = NULL;
- GTMCRYPT_ONLY(GTMCRYPT_CLOSE;)
#ifdef UNIX
gtmsecshr_sock_cleanup(CLIENT);
#ifndef MUTEX_MSEM_WAKE
diff --git a/sr_port/gv_xform_key.c b/sr_port/gv_xform_key.c
index e693ae5..d972325 100644
--- a/sr_port/gv_xform_key.c
+++ b/sr_port/gv_xform_key.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -77,9 +77,8 @@ void gv_xform_key(gv_key *keyp, boolean_t xback)
} else
{
TREF(transform) = xback;
- (TREF(gv_sparekey_mval)).str.len
- = gvsub2str(c0, (unsigned char *)((TREF(gv_sparekey_mval)).str.addr), FALSE)
- - (unsigned char *)(TREF(gv_sparekey_mval)).str.addr;
+ (TREF(gv_sparekey_mval)).str.len = gvsub2str(c0, &((TREF(gv_sparekey_mval)).str), FALSE)
+ - (unsigned char *)(TREF(gv_sparekey_mval)).str.addr;
TREF(transform) = !xback;
mval2subsc(TADR(gv_sparekey_mval), keyp, gv_cur_region->std_null_coll);
c1 = &keyp->base[keyp->end];
diff --git a/sr_port/gvcst_init.c b/sr_port/gvcst_init.c
index f97c6b0..077c324 100644
--- a/sr_port/gvcst_init.c
+++ b/sr_port/gvcst_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -135,8 +135,8 @@ void assert_jrec_member_offsets(void)
/* Following assert is for JNL_FILE_TAIL_PRESERVE macro in tp.h */
assert(PINI_RECLEN >= EPOCH_RECLEN && PINI_RECLEN >= PFIN_RECLEN && PINI_RECLEN >= EOF_RECLEN);
/* jnl_string structure has a 8-bit nodeflags field and a 24-bit length field. In some cases, this is
- * used as a 32-bit length field (e.g. in the value part of the SET record or ZTWORMHOLE record). These
- * usages treat the 32-bits as a jnl_str_len_t type and access it directly. Hence the requirement that
+ * used as a 32-bit length field (e.g. in the value part of the SET record or ZTWORMHOLE or LGTRIG record).
+ * These usages treat the 32-bits as a jnl_str_len_t type and access it directly. Hence the requirement that
* jnl_str_len_t be the same size as 32-bits and also the same as the offset to the "text" member.
* If this assert fails, all places that reference jnl_str_len_t need to be revisited.
*/
@@ -153,11 +153,13 @@ void assert_jrec_member_offsets(void)
assert(offsetof(struct_jrec_null, jnl_seqno) == offsetof(struct_jrec_eof, jnl_seqno));
assert(offsetof(struct_jrec_null, jnl_seqno) == offsetof(struct_jrec_tcom, token_seq.jnl_seqno));
assert(offsetof(struct_jrec_null, jnl_seqno) == offsetof(struct_jrec_ztworm, token_seq.jnl_seqno));
+ assert(offsetof(struct_jrec_null, jnl_seqno) == offsetof(struct_jrec_lgtrig, token_seq.jnl_seqno));
/* Make sure all strm_seqno fields start at same offset. Lot of modules rely on this */
assert(offsetof(struct_jrec_null, strm_seqno) == offsetof(struct_jrec_upd, strm_seqno));
assert(offsetof(struct_jrec_null, strm_seqno) == offsetof(struct_jrec_tcom, strm_seqno));
assert(offsetof(struct_jrec_null, strm_seqno) == offsetof(struct_jrec_ztworm, strm_seqno));
+ assert(offsetof(struct_jrec_null, strm_seqno) == offsetof(struct_jrec_lgtrig, strm_seqno));
/* EOF and EPOCH are not included in the above asserts because they have not ONE but 16 strm_seqno values each */
assert(offsetof(struct_jrec_ztcom, token) == offsetof(struct_jrec_upd, token_seq));
@@ -412,7 +414,7 @@ void gvcst_init(gd_region *greg)
assert(36 == MAX_REL_NAME);
# ifdef UNIX
START_HEARTBEAT_IF_NEEDED;
- if (!pool_init && jnlpool_init_needed && ANTICIPATORY_FREEZE_AVAILABLE && REPL_INST_AVAILABLE)
+ if (!pool_init && jnlpool_init_needed && CUSTOM_ERRORS_AVAILABLE && REPL_INST_AVAILABLE)
jnlpool_init(GTMRELAXED, (boolean_t)FALSE, (boolean_t *)NULL);
/* Any LSEEKWRITEs hence forth will wait if the instance is frozen. To aid in printing the region information before
* and after the wait, csa->region is referenced. Since it is NULL at this point, set it to greg. This is a safe
@@ -495,7 +497,24 @@ void gvcst_init(gd_region *greg)
*/
csa->pblk_align_jrecsize = (int4)MIN_PBLK_RECLEN + csd->blk_size + (int4)MIN_ALIGN_RECLEN;
segment_update_array_size = UA_SIZE(csd);
-
+ assert(!greg->was_open);
+ SET_REGION_OPEN_TRUE(greg, WAS_OPEN_FALSE);
+ if (NULL != csa->dir_tree)
+ { /* It is possible that dir_tree has already been targ_alloc'ed. This is because GT.CM or VMS DAL
+ * calls can run down regions without the process halting out. We don't want to double malloc.
+ */
+ csa->dir_tree->clue.end = 0;
+ }
+ SET_CSA_DIR_TREE(csa, greg->max_key_size, greg);
+ /* Now that reg->open is set to TRUE and directory tree is initialized, go ahead and set rts_error back to being usable */
+ UNIX_ONLY(DBG_MARK_RTS_ERROR_USABLE);
+ /* gds_rundown if invoked from now on will take care of cleaning up the shared memory segment */
+ /* The below code, until the ENABLE_INTERRUPTS(INTRPT_IN_GVCST_INIT), can do mallocs which in turn can issue a
+ * GTM-E-MEMORY error which would invoke rts_error. Hence these have to be done AFTER the
+ * UNIX_ONLY(DBG_MARK_RTS_ERROR_USABLE) call. Since these are only private memory initializations, it is safe to
+ * do these after reg->open is set. Any rts_errors from now on still do the needful cleanup of shared memory in
+ * gds_rundown since reg->open is already TRUE.
+ */
if (first_ua == NULL)
{ /* first open of first database - establish an update array system */
assert(update_array == NULL);
@@ -589,18 +608,6 @@ void gvcst_init(gd_region *greg)
global_tlvl_info_list = (buddy_list *)malloc(SIZEOF(buddy_list));
initialize_list(global_tlvl_info_list, SIZEOF(global_tlvl_info), GBL_TLVL_INFO_LIST_INIT_ALLOC);
}
- assert(!greg->was_open);
- SET_REGION_OPEN_TRUE(greg, WAS_OPEN_FALSE);
- if (NULL != csa->dir_tree)
- { /* It is possible that dir_tree has already been targ_alloc'ed. This is because GT.CM or VMS DAL
- * calls can run down regions without the process halting out. We don't want to double malloc.
- */
- csa->dir_tree->clue.end = 0;
- }
- SET_CSA_DIR_TREE(csa, greg->max_key_size, greg);
- /* Now that reg->open is set to TRUE and directory tree is initialized, go ahead and set rts_error back to being usable */
- UNIX_ONLY(DBG_MARK_RTS_ERROR_USABLE);
- /* gds_rundown if invoked from now on will take care of cleaning up the shared memory segment */
ENABLE_INTERRUPTS(INTRPT_IN_GVCST_INIT);
if (dba_bg == greg_acc_meth)
{ /* Check if (a) this region has non-upgraded blocks and if so, (b) the reformat buffer exists and
diff --git a/sr_port/gvcst_put.c b/sr_port/gvcst_put.c
index b2586e9..4a42f8a 100644
--- a/sr_port/gvcst_put.c
+++ b/sr_port/gvcst_put.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -147,6 +147,7 @@ error_def(ERR_DBROLLEDBACK);
error_def(ERR_GVINCRISOLATION);
error_def(ERR_GVIS);
error_def(ERR_GVPUTFAIL);
+error_def(ERR_MAXBTLEVEL);
error_def(ERR_REC2BIG);
error_def(ERR_RSVDBYTE2HIGH);
error_def(ERR_TEXT);
@@ -2267,9 +2268,13 @@ tn_restart:
{ /* Create new root */
if ((bh_level + 1) == MAX_BT_DEPTH)
{
- assert(CDB_STAGNATE > t_tries);
- status = cdb_sc_maxlvl;
- GOTO_RETRY;
+ if (CDB_STAGNATE > t_tries)
+ {
+ status = cdb_sc_maxlvl;
+ GOTO_RETRY;
+ }
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_MAXBTLEVEL, 4, gv_target->gvname.var_name.len,
+ gv_target->gvname.var_name.addr, REG_LEN_STR(gv_cur_region));
}
ins_chain_index = t_create(blk_num, (uchar_ptr_t)bs1, ins_chain_offset, ins_chain_index, bh_level);
make_it_null = FALSE;
diff --git a/sr_port/gvcst_search.c b/sr_port/gvcst_search.c
index ae1b082..2c6a0cb 100644
--- a/sr_port/gvcst_search.c
+++ b/sr_port/gvcst_search.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -78,6 +78,9 @@ enum cdb_sc gvcst_search(gv_key *pKey, /* Key to search for */
sm_uc_ptr_t buffaddr;
trans_num blkhdrtn, oldest_hist_tn;
int hist_size;
+# ifdef DEBUG
+ boolean_t save_donot_commit;
+# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -116,6 +119,7 @@ enum cdb_sc gvcst_search(gv_key *pKey, /* Key to search for */
assert(!mu_reorg_process UNIX_ONLY(|| (pTarg->gd_csa->dir_tree == pTarg)));
INCR_DB_CSH_COUNTER(cs_addrs, n_gvcst_srch_clues, 1);
status = cdb_sc_normal; /* clue is usable unless proved otherwise */
+ DEBUG_ONLY(save_donot_commit = TREF(donot_commit);)
if (NULL != pHist)
{ /* Copy the full srch_hist and set loop terminator flag in unused srch_blk_status entry.
* If in TP and if leaf block in history has cse, we are guaranteed that it is built by the
@@ -238,17 +242,19 @@ enum cdb_sc gvcst_search(gv_key *pKey, /* Key to search for */
leaf_blk_hist->cycle = CYCLE_PVT_COPY;
leaf_blk_hist->buffaddr = cse->new_buff;
} else
- { /* Keep leaf_blk_hist->buffaddr and cse->new_buff in sync. If a TP transaction
- * updates two different globals and the second update invoked t_qread for a leaf
- * block corresponding to the first global and ended up constructing a private block
- * then leaf_blk_hist->buffaddr of the first global will be out-of-sync with the
- * cse->new_buff. However, the transaction validation done in tp_hist/tp_tend
- * should detect this and restart. Set donot_commit to verify that a restart happens
+ { /* Keep leaf_blk_hist->buffaddr and cse->new_buff in sync if they are not already.
+ * They will be mostly in sync except for two cases.
+ * a) If a TP transaction updates two different globals and the second update
+ * invoked t_qread (invoked from outside gvcst_search) for a leaf block
+ * corresponding to the first global and ended up constructing a private
+ * block. However, the transaction validation done in tp_hist/tp_tend
+ * should detect this and restart.
+ * b) If a gvcst_kill happens in a TP transaction and it does a gvcst_search
+ * call without going through tp_hist (GTM-8120). In this case there is no
+ * restartable situation.
+ * Since it is hard to distinguish (a) from (b), we do not set the donot_commit
+ * variable to indicate this is a restartable situation in case of just (a).
*/
-# ifdef DEBUG
- if (leaf_blk_hist->buffaddr != cse->new_buff)
- TREF(donot_commit) |= DONOTCOMMIT_GVCST_SEARCH_LEAF_BUFFADR_NOTSYNC;
-# endif
leaf_blk_hist->buffaddr = cse->new_buff; /* sync the buffers in pro, just in case */
}
}
@@ -360,6 +366,13 @@ enum cdb_sc gvcst_search(gv_key *pKey, /* Key to search for */
return cdb_sc_normal;
}
}
+# ifdef DEBUG
+ /* If we are not going to use this clue (i.e. going to read the entire GVT afresh),
+ * restore global variable donot_commit in case it got set to a non-zero value above.
+ * This is needed because we are no longer relying on the out-of-date (and restart causing) clue.
+ */
+ TREF(donot_commit) = save_donot_commit;
+# endif
}
nBlkId = pTarg->root;
tn = cs_addrs->ti->curr_tn;
diff --git a/sr_port/gvstrsub.c b/sr_port/gvstrsub.c
deleted file mode 100644
index da36634..0000000
--- a/sr_port/gvstrsub.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************
- * *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
- * *
- * This source code contains the intellectual property *
- * of its copyright holder(s), and is made available *
- * under a license. If you do not know the terms of *
- * the license, please stop and do not read further. *
- * *
- ****************************************************************/
-
-#include "mdef.h"
-
-#include "gdsroot.h"
-#include "gtm_facility.h"
-#include "fileinfo.h"
-#include "gdsbt.h"
-#include "collseq.h"
-#include "gdsfhead.h"
-#include "do_xform.h"
-#include "gvstrsub.h"
-#include "zshow.h"
-
-GBLREF gv_namehead *gv_target;
-
-unsigned char *gvstrsub(unsigned char *src, unsigned char *target)
-{
- int length, n, target_len;
- char buf[MAX_KEY_SZ + 1], buf1[MAX_KEY_SZ + 1], *ptr;
- unsigned char *str;
- mstr mstr_x;
- mstr mstr_tmp;
- DCL_THREADGBL_ACCESS;
-
- SETUP_THREADGBL_ACCESS;
- ptr = buf;
- for (n = 0, str = src; *str; ++n, ++str)
- {
- if (1 == *str)
- {
- str++;
- *ptr++ = *str - 1;
- } else
- *ptr++ = *str;
- }
- if (TREF(transform) && gv_target && gv_target->collseq)
- {
- mstr_x.len = n;
- mstr_x.addr = buf;
- mstr_tmp.len = SIZEOF(buf1);
- mstr_tmp.addr = buf1;
- do_xform(gv_target->collseq, XBACK, &mstr_x, &mstr_tmp, &length);
- n = length;
- str = (unsigned char *)mstr_tmp.addr; /* mstr_tmp.addr is used just in case it is
- reallocated in the XBACK routine */
- } else
- str = (unsigned char *)buf;
- format2zwr((sm_uc_ptr_t)str, n, target, &target_len);
- return target + target_len;
-}
diff --git a/sr_port/gvsub2str.c b/sr_port/gvsub2str.c
index 6a17b36..6052949 100644
--- a/sr_port/gvsub2str.c
+++ b/sr_port/gvsub2str.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -35,6 +35,7 @@
GBLREF gv_namehead *gv_target;
LITREF unsigned short dpos[], dneg[];
+error_def(ERR_GVSUBOFLOW);
/*
* -----------------------------------------------------
* Convert a string subscript to MUMPS string
@@ -42,7 +43,7 @@ LITREF unsigned short dpos[], dneg[];
*
* Entry:
* sub - input string in subscript format
- * targ - output string buffer
+ * targ - output mstr value.
* xlat_flg- translate flag.
* If true convert string to MUMPS format (aka ZWRITE format)
* Return:
@@ -50,9 +51,9 @@ LITREF unsigned short dpos[], dneg[];
* converted in the targ string) + 1.
* -----------------------------------------------------
*/
-unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat_flg)
+unsigned char *gvsub2str(unsigned char *sub, mstr *opstr, boolean_t xlat_flg)
{
- unsigned char buf[MAX_KEY_SZ + 1], buf1[MAX_KEY_SZ + 1], ch, *ptr, trail_ch, *str;
+ unsigned char buf[MAX_KEY_SZ + 1], buf1[MAX_KEY_SZ + 1], ch, *ptr, trail_ch, *str, *targ, *targ_end;
unsigned short *tbl_ptr;
int num, rev_num, trail_zero;
span_subs *subs_ptr;
@@ -62,6 +63,7 @@ unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat
SETUP_THREADGBL_ACCESS;
ch = *sub++;
+ targ = (unsigned char *)opstr->addr;
if (STR_SUB_PREFIX == ch || (SUBSCRIPT_STDCOL_NULL == ch && KEY_DELIMITER == *sub))
{ /* If this is a string */
in_length = 0;
@@ -80,6 +82,14 @@ unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat
mstr_targ.len = SIZEOF(buf1);
mstr_targ.addr = (char *)buf1;
do_xform(gv_target->collseq, XBACK, &mstr_ch, &mstr_targ, &targ_len);
+ if (targ_len > opstr->len)
+ {
+ /* The only way we know of for targ_len to be greater than opstr->len is if the collation
+ * library allocated an external buffer greater than opstr->len
+ */
+ assert(mstr_targ.addr != (char *)buf1);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GVSUBOFLOW);
+ }
if (!xlat_flg)
{
memcpy(targ, mstr_targ.addr, targ_len); /* mstr_targ.addr is used just in case it is
@@ -100,10 +110,13 @@ unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat
if (xlat_flg)
{
format2zwr((sm_uc_ptr_t)ptr, in_length, targ, &targ_len);
+ assert(targ_len <= opstr->len);
targ = targ + targ_len;
}
} else
{ /* Number */
+ targ_end = targ + opstr->len;
+ assert(opstr->len >= SPAN_PREFIX_LEN);
if (SUBSCRIPT_ZERO == ch)
*targ++ = '0';
else if(SPANGLOB_SUB_ESCAPE == ch)
@@ -121,9 +134,10 @@ unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat
;
for (rev_num = 0; num > 0; rev_num = (rev_num * DECIMAL_BASE + num % DECIMAL_BASE), num /= DECIMAL_BASE)
;
- for (; rev_num > 0; *targ++ = (rev_num % DECIMAL_BASE + ASCII_0), rev_num /= DECIMAL_BASE)
+ for (; rev_num > 0 && targ < targ_end;
+ *targ++ = (rev_num % DECIMAL_BASE + ASCII_0), rev_num /= DECIMAL_BASE)
;
- for (; trail_zero > 0 ; *targ++ = '0', trail_zero--);
+ for (; trail_zero > 0 && targ < targ_end; *targ++ = '0', trail_zero--);
if (*sub != 0)
*targ++ = '*';
}
@@ -131,7 +145,7 @@ unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat
{
tbl_ptr = (unsigned short *)&dpos[0] - 1;
trail_ch = KEY_DELIMITER;
- if (0 <= (signed char)ch)
+ if (0 <= (signed char)ch && targ < targ_end)
{ /* Bit 7 of the exponent is set for positive numbers; must be negative */
trail_ch = NEG_MNTSSA_END;
tbl_ptr = (unsigned short *)dneg;
@@ -147,7 +161,7 @@ unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat
*targ++ = '.';
/* generate leading 0's */
do *targ++ = '0';
- while ((signed char)ch-- > 0)
+ while ((signed char)ch-- > 0 && targ < targ_end)
;
/* make expon. really large to avoid
* generating extra dots */
@@ -186,7 +200,7 @@ unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat
if ('.' == *(targ - 1))
targ--;
} else
- while (--expon > 0)
+ while (--expon > 0 && targ < targ_end)
*targ++ = '0';
}
}
diff --git a/sr_port/gvsub2str.h b/sr_port/gvsub2str.h
index e5b6bb2..ed3b67b 100644
--- a/sr_port/gvsub2str.h
+++ b/sr_port/gvsub2str.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,6 @@
#ifndef GVSUB2STR_INCLUDED
#define GVSUB2STR_INCLUDED
-unsigned char *gvsub2str(unsigned char *sub, unsigned char *targ, boolean_t xlat_flg);
+unsigned char *gvsub2str(unsigned char *sub, mstr *targ, boolean_t xlat_flg);
#endif /* GVSUB2STR_INCLUDED */
diff --git a/sr_port/gvzwr_fini.c b/sr_port/gvzwr_fini.c
index c1ed39e..38cf689 100644
--- a/sr_port/gvzwr_fini.c
+++ b/sr_port/gvzwr_fini.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -39,6 +39,7 @@ GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF gvzwrite_datablk *gvzwrite_block;
GBLREF gd_addr *gd_header;
+GBLREF bool undef_inhibit;
error_def(ERR_GVNAKED);
@@ -75,8 +76,10 @@ void gvzwr_fini(zshow_out *out, int pat)
op_gvname(VARLSTCNT(1) &local);
op_gvdata(&data);
if (!(MV_FORCE_INTD(&data)))
- sgnl_gvundef();
- else
+ {
+ if (!undef_inhibit)
+ sgnl_gvundef();
+ } else
{
gvzwrite_block->fixed = (gvzwrite_block->fixed ? TRUE : FALSE);
gvzwr_var(MV_FORCE_INTD(&data), 0);
@@ -95,8 +98,10 @@ void gvzwr_fini(zshow_out *out, int pat)
GV_BIND_SUBSNAME_FROM_GVNH_REG_IF_GVSPAN(gvnh_reg, gd_header, gv_currkey);
op_gvdata(&data);
if (!(MV_FORCE_INTD(&data)))
- sgnl_gvundef();
- else
+ {
+ if (!undef_inhibit)
+ sgnl_gvundef();
+ } else
{
gvzwrite_block->fixed = (gvzwrite_block->fixed ? TRUE : FALSE);
gvzwr_var((int4)MV_FORCE_INTD(&data), 0);
diff --git a/sr_port/gvzwr_var.c b/sr_port/gvzwr_var.c
index 8c2ef98..b82dcd7 100644
--- a/sr_port/gvzwr_var.c
+++ b/sr_port/gvzwr_var.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,6 +33,7 @@ GBLREF gvzwrite_datablk *gvzwrite_block;
GBLREF int4 outofband;
GBLREF gd_region *gv_cur_region;
GBLREF gd_addr *gd_header;
+GBLREF bool undef_inhibit;
LITREF mval literal_null;
@@ -78,7 +79,7 @@ void gvzwr_var(uint4 data, int4 n)
save_gv_last_subsc_null = TREF(gv_last_subsc_null);
gvzwr_var((int4)MV_FORCE_INTD(&subdata), n + 1);
TREF(gv_last_subsc_null) = save_gv_last_subsc_null;
- } else if (gvzwrite_block->fixed)
+ } else if (gvzwrite_block->fixed && (!undef_inhibit))
sgnl_gvundef();
} else
{
diff --git a/sr_port/indir.h b/sr_port/indir.h
index 309a1d7..573220b 100644
--- a/sr_port/indir.h
+++ b/sr_port/indir.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -85,4 +85,6 @@ INDIR(indir_fndata, f_data, OC_FNDATA)
,INDIR(indir_savglvn0, indirection, 0) /* this entry and the following use indirection as a dummy value */
,INDIR(indir_savlvn, indirection, 0)
,INDIR(indir_savglvn1, indirection, 0) /* 0 and 1 (above) separate 2 variants of generated code */
-
+#ifdef USHBIN_SUPPORTED
+,INDIR(indir_zrupdate, m_zrupdate, 0)
+#endif
diff --git a/sr_port/insert_region.c b/sr_port/insert_region.c
index bb47273..7a11573 100644
--- a/sr_port/insert_region.c
+++ b/sr_port/insert_region.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -62,11 +62,15 @@ GBLREF gd_region *gv_cur_region;
GBLREF uint4 dollar_tlevel;
GBLREF unsigned int t_tries;
+error_def(ERR_DBFILOPERR);
+
tp_region *insert_region( gd_region *reg,
tp_region **reg_list,
tp_region **reg_free_list,
int4 size)
{
+ int4 local_fid_index, match;
+ sgmnt_addrs *csa;
tp_region *tr, *tr_last, *tr_new;
unique_file_id local_id;
# ifdef VMS
@@ -74,10 +78,9 @@ tp_region *insert_region( gd_region *reg,
file_control *fc;
uint4 status;
gd_region *temp_reg;
+# elif UNIX
+ int save_errno;
# endif
- int4 local_fid_index;
- sgmnt_addrs *csa;
- int4 match;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -107,7 +110,7 @@ tp_region *insert_region( gd_region *reg,
sys$dassgn(FILE_INFO(reg)->fab->fab$l_stv);
} else
{
- gtm_putmsg(VARLSTCNT(1) status);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
gv_cur_region = temp_reg;
return NULL;
}
@@ -119,8 +122,11 @@ tp_region *insert_region( gd_region *reg,
{
if (!mupfndfil(reg, NULL))
return NULL;
- if (!filename_to_id(&local_id.uid, (char *)reg->dyn.addr->fname))
+ if (SS_NORMAL != (save_errno = filename_to_id(&local_id.uid, (char *)reg->dyn.addr->fname)))
+ { /* WARNING: assignment above */
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_DBFILOPERR, 2, LEN_AND_STR(reg->dyn.addr->fname), save_errno);
return NULL;
+ }
} else
local_fid_index = csa->fid_index;
# endif
diff --git a/sr_port/io.h b/sr_port/io.h
index c5ecc39..c1e0e22 100644
--- a/sr_port/io.h
+++ b/sr_port/io.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,6 +21,7 @@
#include <sys/types.h>
#endif
#endif
+#include <stdarg.h>
#include "gt_timer.h"
#include <rtnhdr.h>
@@ -203,7 +204,7 @@ typedef struct dev_dispatch_struct
void (*wttab)(int4);
void (*flush)(io_desc *);
int (*readfl)(mval *, int4, int4);
- void (*iocontrol)(mstr *);
+ void (*iocontrol)(mstr *, int4, va_list);
void (*dlr_device)(mstr *);
void (*dlr_key)(mstr *);
void (*dlr_zkey)(mstr *);
@@ -211,7 +212,7 @@ typedef struct dev_dispatch_struct
/* io_ prototypes */
void io_rundown(int rundown_type);
-void io_init(bool term_ctrl);
+void io_init(boolean_t term_ctrl);
bool io_is_rm(mstr *name);
bool io_is_sn(mstr *tn);
struct mv_stent_struct *io_find_mvstent(io_desc *io_ptr, boolean_t clear_mvstent);
@@ -235,7 +236,7 @@ void io_init_name(void);
#define ioxx_wttab(X) void io##X##_wttab(int4 x)
#define ioxx_flush(X) void io##X##_flush(io_desc *iod)
#define ioxx_readfl(X) int io##X##_readfl(mval *v, int4 width, int4 timeout)
-#define xx_iocontrol(X) void X##_iocontrol(mstr *d)
+#define xx_iocontrol(X) void X##_iocontrol(mstr *mn, int4 argcnt, va_list args)
#define xx_dlr_device(X) void X##_dlr_device(mstr *d)
#define xx_dlr_key(X) void X##_dlr_key(mstr *d)
#define xx_dlr_zkey(X) void X##_dlr_zkey(mstr *d)
@@ -272,7 +273,7 @@ xxdlrzk(iosocket);
ioxx_open(ff);
#ifdef UNIX
ioxx_open(pi);
-xxdlr(iopi); /* we need iopi_iocontrol(), iopi_dlr_device() and iopi_dlr_key() */
+xxdlrzk(iopi); /* we need iopi_iocontrol(), iopi_dlr_device(), iopi_dlr_key() and iopi_dlr_zkey() */
xxdlr(iott); /* we need iott_iocontrol(), iott_dlr_device() and iott_dlr_key() */
#endif
ioxx_wttab(us);
@@ -306,6 +307,10 @@ void iomt_wtdoslab(io_desc *dv);
boolean_t iosocket_listen(io_desc *iod, unsigned short len);
boolean_t iosocket_wait(io_desc *iod, int4 timepar);
void iosocket_poolinit(void);
+#ifndef VMS
+void iosocket_pass_local(io_desc *iod, pid_t pid, int4 timeout, int argcnt, va_list args);
+void iosocket_accept_local(io_desc *iod, mval *handlevar, pid_t pid, int4 timeout, int argcnt, va_list args);
+#endif
/* tcp_ prototypes */
int tcp_open(char *host, unsigned short port, int4 timeout, boolean_t passive);
@@ -403,16 +408,18 @@ LITREF unsigned char ebcdic_spaces_block[];
asc_to_ebc(*(DEST), *(SRC), *(IN_LEN_PTR)); \
}
-#define SET_ENCODING(CHSET, CHSET_MSTR) \
+/* iosocket_open needs to prevent changing chset sometimes */
+#define SET_ENCODING_VALIDATE(CHSET, CHSET_MSTR, VALIDATE) \
{ \
int chset_idx; \
\
chset_idx = verify_chset(CHSET_MSTR); \
- ; \
+ VALIDATE; \
if (0 <= chset_idx) \
(CHSET) = (gtm_chset_t)chset_idx; \
else \
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADCHSET, 2, (CHSET_MSTR)->len, (CHSET_MSTR)->addr); \
}
+#define SET_ENCODING(CHSET, CHSET_MSTR) SET_ENCODING_VALIDATE(CHSET, CHSET_MSTR,)
#endif /* IO_H */
diff --git a/sr_port/io_dev_dispatch.h b/sr_port/io_dev_dispatch.h
index 746e656..c44ea9b 100644
--- a/sr_port/io_dev_dispatch.h
+++ b/sr_port/io_dev_dispatch.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,7 +24,7 @@ UNIX_ONLY(GBLDEF) VMS_ONLY(LITDEF) dev_dispatch_struct io_dev_dispatch[] =
# endif
iotype(iomt, iomt, nil, nil),
# ifdef UNIX
- iotype(iorm, iorm, iopi, nil),
+ iotype(iorm, iorm, iopi, iopi),
# else
iotype(iorm, iorm, nil, nil),
# endif
@@ -42,6 +42,6 @@ UNIX_ONLY(GBLDEF) VMS_ONLY(LITDEF) dev_dispatch_struct io_dev_dispatch[] =
# endif
iotype(iosocket, iosocket, iosocket, iosocket)
# ifdef UNIX
- ,iotype(iopi, iorm, iopi, nil)
+ ,iotype(iopi, iorm, iopi, iopi)
# endif
};
diff --git a/sr_port/io_init.c b/sr_port/io_init.c
index 0c60c15..3a61be2 100644
--- a/sr_port/io_init.c
+++ b/sr_port/io_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,9 @@
#include "mdef.h"
#include "gtm_string.h"
+#ifdef UNIX
+#include "gtmio.h"
+#endif
#include "io.h"
#include "iosp.h"
@@ -20,7 +23,6 @@
#include "op.h"
#include "term_setup.h"
#include "trans_log_name.h"
-/***************** GLOBAL DATA FOR THE MUMPS IO SYSTEM *******************/
GBLREF io_pair io_curr_device; /* current device */
GBLREF io_pair io_std_device; /* standard device */
@@ -33,43 +35,88 @@ GBLREF io_log_name *io_root_log_name; /* root of linked list */
GBLREF mstr sys_input;
GBLREF mstr sys_output;
GBLREF mstr gtm_principal;
+#ifdef UNIX
+GBLREF boolean_t err_same_as_out;
+#endif
+error_def(ERR_FILEOPENFAIL);
+error_def(ERR_LOGTOOLONG);
+error_def(ERR_SYSCALL);
-/***************** END OF GLOBAL DATA ***************************************/
-
-
-void io_init(bool term_ctrl)
+void io_init(boolean_t term_ctrl)
{
static readonly unsigned char open_params_list[2] =
{
(unsigned char)iop_newversion,
(unsigned char)iop_eol
};
- static readonly unsigned char null_params_list[2] =
+ static readonly unsigned char nolognam_params_list[] =
{
+# ifdef UNIX
+ (unsigned char)iop_stream, /* open FILEs in Unix with STREAM option by default */
+# endif
(unsigned char)iop_nl,
(unsigned char)iop_eol
};
+# ifdef UNIX
+ static readonly unsigned char nowrap_params_list[] =
+ {
+ (unsigned char)iop_nowrap,
+ (unsigned char)iop_eol
+ };
+# endif
static readonly unsigned char no_params = (unsigned char)iop_eol;
- static readonly unsigned char shr_params[3] =
+ static readonly unsigned char shr_params[] =
{
(unsigned char)iop_shared,
(unsigned char)iop_readonly,
(unsigned char)iop_eol
};
- int4 status;
- mval val;
- mstr tn;
- MSTR_CONST (gtm_netout, "GTM_NETOUT");
- MSTR_CONST (sys_net, "SYS$NET");
- char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */
- mval pars;
- io_log_name *inp, *outp;
- io_log_name *ln;
-
- error_def(ERR_LOGTOOLONG);
+ int4 status;
+ mval val;
+ mstr tn;
+ MSTR_CONST (gtm_netout, "GTM_NETOUT");
+ MSTR_CONST (sys_net, "SYS$NET");
+ char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */
+ mval pars;
+ io_log_name *inp, *outp;
+ io_log_name *ln;
+ enum io_dev_type dev_type;
+# ifdef UNIX
+ int fd, newfd;
+ struct stat statbuf, out_statbuf;
+# endif
+# ifdef UNIX
+ /* Make sure we have valid descriptors on stdin/stdout/stderr.
+ * Otherwise we could end up "filling the hole" with a database file and writing an error message to it.
+ */
+ for (fd = 0; fd < 3; fd++)
+ {
+ status = fstat(fd, &statbuf);
+ if (-1 == status)
+ {
+ if (EBADF == errno)
+ {
+ OPENFILE("/dev/null", ((0 == fd) ? O_RDONLY : O_RDWR), newfd);
+ if (-1 == newfd)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_SYSCALL, 5,
+ LEN_AND_LIT("open /dev/null on std descriptor"), CALLFROM, errno, 0);
+ assert(newfd == fd);
+ }
+ else
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_SYSCALL, 5,
+ LEN_AND_LIT("fstat of std descriptor"), CALLFROM, errno, 0);
+ } else if (0 < fd)
+ {
+ if (1 == fd)
+ out_statbuf = statbuf;
+ else
+ err_same_as_out = (statbuf.st_dev == out_statbuf.st_dev) && (statbuf.st_ino == out_statbuf.st_ino);
+ }
+ }
+# endif
io_init_name();
/* default logical names */
io_root_log_name = (io_log_name *)malloc(SIZEOF(*io_root_log_name));
@@ -87,10 +134,10 @@ void io_init(bool term_ctrl)
dollar_principal = get_log_name(&tn, INSERT);
# ifdef UNIX
else if (SS_LOG2LONG == status)
- rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1);
# endif
else
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
/* open devices */
val.str = sys_input;
@@ -99,10 +146,11 @@ void io_init(bool term_ctrl)
status = TRANS_LOG_NAME(&val.str, &tn, buf1, SIZEOF(buf1), dont_sendmsg_on_log2long);
if (SS_NOLOGNAM == status)
{
- pars.str.len = SIZEOF(null_params_list);
- pars.str.addr = (char *)null_params_list;
+ pars.str.len = SIZEOF(nolognam_params_list);
+ pars.str.addr = (char *)nolognam_params_list;
} else if (SS_NORMAL == status)
{
+ UNIX_ONLY(assert(FALSE);)
if (!io_is_rm(&val.str))
{
pars.str.len = SIZEOF(no_params);
@@ -119,10 +167,10 @@ void io_init(bool term_ctrl)
}
# ifdef UNIX
else if (SS_LOG2LONG == status)
- rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1);
# endif
else
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
ESTABLISH(io_init_ch);
(*op_open_ptr)(&val, &pars, 0, 0);
io_curr_device.in = io_std_device.in = inp->iod;
@@ -137,10 +185,10 @@ void io_init(bool term_ctrl)
{
# ifdef UNIX
if (SS_LOG2LONG == status)
- rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1);
else
# endif
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
if ((val.str.addr == sys_net.addr) && (pars.str.addr == (char *)open_params_list))
/* sys$net is the only input thing that uses open_params_list */
@@ -149,16 +197,15 @@ void io_init(bool term_ctrl)
the same device. If input is one of those, then check translated
name for output against translated name for input;
in that case they should be joined by their logical names */
- if (((tt == io_curr_device.in->type) || (mb == io_curr_device.in->type) ||
- (gtmsocket == io_curr_device.in->type))
- && same_device_check(tn, buf1))
+ dev_type = io_curr_device.in->type;
+ if (((tt == dev_type) || (mb == dev_type) || (gtmsocket == dev_type)) && same_device_check(tn, buf1))
outp->iod = io_curr_device.in;
if (!outp->iod)
{
if (status == SS_NOLOGNAM)
{
- pars.str.len = SIZEOF(null_params_list);
- pars.str.addr = (char *)null_params_list;
+ pars.str.len = SIZEOF(nolognam_params_list);
+ pars.str.addr = (char *)nolognam_params_list;
} else if (status == SS_NORMAL)
{
pars.str.len = SIZEOF(open_params_list);
@@ -178,6 +225,16 @@ void io_init(bool term_ctrl)
dollar_principal->iod = io_std_device.in;
pars.str.len = SIZEOF(no_params);
pars.str.addr = (char *)&no_params;
+# ifdef UNIX
+ /* If Unix and input/output device is one of rm (FILE) or ff (FIFO) or pi (PIPE) or gtmsocket (SOCKET),
+ * open device by default with NOWRAP option.
+ */
+ if ((rm == dev_type) || (ff == dev_type) || (pi == dev_type) || (gtmsocket == dev_type))
+ {
+ pars.str.len = SIZEOF(nowrap_params_list);
+ pars.str.addr = (char *)nowrap_params_list;
+ }
+# endif
val.str.len = io_curr_device.in->trans_name->len;
val.str.addr = io_std_device.in->trans_name->dollar_io;
op_use(&val, &pars);
diff --git a/sr_port/io_init_ch.c b/sr_port/io_init_ch.c
index 8b1d1b9..6db0a0d 100644
--- a/sr_port/io_init_ch.c
+++ b/sr_port/io_init_ch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -26,11 +26,13 @@ CONDITION_HANDLER(io_init_ch)
io_log_name *iol;
START_CH(TRUE);
+# ifdef VMS
if (INFO == SEVERITY)
{
PRN_ERROR;
CONTINUE;
}
+# endif
for (iol = io_root_log_name; 0 != iol; iol = iol->next)
{
if (iol->iod && (iol->iod->type == tt) && iol->iod->dev_sp)
diff --git a/sr_port/iop.h b/sr_port/iop.h
index 711216f..37f4f2f 100644
--- a/sr_port/iop.h
+++ b/sr_port/iop.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -215,4 +215,12 @@ IOP_DESC(197, iop_nofollow, 0, IOP_OPEN_OK|IOP_USE_OK, 0),
IOP_DESC(198, iop_empterm, 0, IOP_OPEN_OK|IOP_USE_OK, 0),
IOP_DESC(199, iop_noempterm, 0, IOP_OPEN_OK|IOP_USE_OK, 0),
IOP_DESC(200, iop_timeout, SIZEOF(int4), IOP_CLOSE_OK, IOP_SRC_INT),
-IOP_DESC(201, n_iops, 0, 0, 0)
+IOP_DESC(201, iop_seek, IOP_VAR_SIZE, IOP_OPEN_OK | IOP_USE_OK, IOP_SRC_STR),
+IOP_DESC(202, iop_key, IOP_VAR_SIZE, IOP_OPEN_OK | IOP_USE_OK, IOP_SRC_STR),
+IOP_DESC(203, iop_input_key, IOP_VAR_SIZE, IOP_OPEN_OK | IOP_USE_OK, IOP_SRC_STR),
+IOP_DESC(204, iop_output_key, IOP_VAR_SIZE, IOP_OPEN_OK | IOP_USE_OK, IOP_SRC_STR),
+IOP_DESC(205, iop_inseek, IOP_VAR_SIZE, IOP_OPEN_OK | IOP_USE_OK, IOP_SRC_STR),
+IOP_DESC(206, iop_outseek, IOP_VAR_SIZE, IOP_OPEN_OK | IOP_USE_OK, IOP_SRC_STR),
+IOP_DESC(207, iop_inrewind, 0, IOP_OPEN_OK | IOP_USE_OK, 0),
+IOP_DESC(208, iop_outrewind, 0, IOP_OPEN_OK | IOP_USE_OK, 0),
+IOP_DESC(209, n_iops, 0, 0, 0)
diff --git a/sr_port/iormdefsp.h b/sr_port/iormdefsp.h
index 2219de2..8ee7d8b 100644
--- a/sr_port/iormdefsp.h
+++ b/sr_port/iormdefsp.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2006 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,9 +16,11 @@
#define ASCII_RMEOL "\n"
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
-#define RMEOL ((ascii != iod->out_code_set) ? EBCDIC_RMEOL : ASCII_RMEOL )
+#define RMEOL ((ascii != iod->out_code_set) ? EBCDIC_RMEOL : ASCII_RMEOL)
+#define RMEOL_LEN ((ascii != iod->out_code_set) ? SIZEOF(EBCDIC_RMEOL) - 1 : SIZEOF(ASCII_RMEOL) - 1)
#else
-#define RMEOL ASCII_RMEOL
+#define RMEOL ASCII_RMEOL
+#define RMEOL_LEN (SIZEOF(ASCII_RMEOL) - 1)
#endif
#endif /* IORMDEFSP_H */
diff --git a/sr_port/iosocket_bind.c b/sr_port/iosocket_bind.c
index f545111..e490d91 100644
--- a/sr_port/iosocket_bind.c
+++ b/sr_port/iosocket_bind.c
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2001, 2013 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
/* iosocket_bind.c */
#include "mdef.h"
diff --git a/sr_port/iosocket_close.c b/sr_port/iosocket_close.c
index 52d26f0..4347f8a 100644
--- a/sr_port/iosocket_close.c
+++ b/sr_port/iosocket_close.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,6 +22,7 @@
#include "gtm_iconv.h"
#ifndef VMS
#include "gtm_stat.h"
+#include "gtmio.h"
#endif
#include "gtm_stdio.h"
#include "gtm_unistd.h"
@@ -37,10 +38,16 @@
#include "stringpool.h"
#include "eintr_wrappers.h"
-GBLREF io_desc *active_device;
+GBLREF io_desc *active_device;
+GBLREF int process_exiting;
+#ifndef VMS
+GBLREF boolean_t gtm_pipe_child;
+#endif
+
LITREF unsigned char io_params_size[];
error_def(ERR_CLOSEFAIL);
+error_def(ERR_FILEOPENFAIL);
error_def(ERR_SOCKNOTFND);
error_def(ERR_SYSCALL);
@@ -66,12 +73,12 @@ void iosocket_close(io_desc *iod, mval *pp)
switch (ch)
{
case iop_exception:
- iod->error_handler.len = *(pp->str.addr + p_offset);
+ iod->error_handler.len = (int)(*(pp->str.addr + p_offset));
iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
s2pool(&iod->error_handler);
break;
case iop_socket:
- handle_len = (short)(*(pp->str.addr + p_offset));
+ handle_len = (int)(*(pp->str.addr + p_offset));
assert(handle_len > 0);
memcpy(sock_handle, (char *)(pp->str.addr + p_offset + 1), handle_len);
socket_specified = TRUE;
@@ -150,14 +157,16 @@ void iosocket_close_range(d_socket_struct *dsocketptr, int start, int end, boole
struct stat statbuf, fstatbuf;
char *path;
int res;
+ int null_fd = 0;
# endif
for (ii = start; ii >= end; ii--)
{
socketptr = dsocketptr->socket[ii];
# ifndef VMS
- if (socket_specified && socket_delete && (socket_local == socketptr->protocol) && socketptr->passive)
- { /* only delete if SOCKET= specified and passive/listening */
+ /* Don't reap if in a child process creating a new job or pipe device */
+ if ((socket_local == socketptr->protocol) && socketptr->passive && !gtm_pipe_child)
+ { /* only delete if passive/listening */
assertpro(socketptr->local.sa);
path = ((struct sockaddr_un *)(socketptr->local.sa))->sun_path;
FSTAT_FILE(socketptr->sd, &fstatbuf, res);
@@ -180,6 +189,17 @@ void iosocket_close_range(d_socket_struct *dsocketptr, int start, int end, boole
save_fd = socketptr->sd;
save_errno = errno;
}
+# ifndef VMS
+ else if (!process_exiting && (3 > socketptr->sd))
+ {
+ OPENFILE("/dev/null", O_RDWR, null_fd);
+ if (-1 == null_fd)
+ {
+ save_errno = errno;
+ }
+ assert(socketptr->sd == null_fd);
+ }
+# endif
SOCKET_FREE(socketptr);
if (dsocketptr->current_socket >= ii)
dsocketptr->current_socket--;
@@ -191,6 +211,12 @@ void iosocket_close_range(d_socket_struct *dsocketptr, int start, int end, boole
{
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CLOSEFAIL, 1, save_fd, save_errno);
}
+# ifndef VMS
+ else if (-1 == null_fd)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_FILEOPENFAIL, 2, LIT_AND_LEN("/dev/null"), save_errno, 0);
+ }
+# endif
}
void iosocket_close_one(d_socket_struct *dsocketptr, int index)
diff --git a/sr_port/iosocket_connect.c b/sr_port/iosocket_connect.c
index 5aaf694..9f3e1f0 100644
--- a/sr_port/iosocket_connect.c
+++ b/sr_port/iosocket_connect.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,6 +16,7 @@
#include "gtm_socket.h"
#include "gtm_inet.h"
#include "gtm_stdio.h"
+#include "gtm_stdlib.h"
#include "gtm_string.h"
#include "stringpool.h"
#include "gt_timer.h"
@@ -43,6 +44,7 @@ GBLREF d_socket_struct *newdsocket; /* in case jobinterrupt */
GBLREF int4 gtm_max_sockets;
error_def(ERR_GETNAMEINFO);
+error_def(ERR_GETSOCKNAMERR);
error_def(ERR_GETSOCKOPTERR);
error_def(ERR_OPENCONN);
error_def(ERR_SETSOCKOPTERR);
@@ -68,10 +70,11 @@ boolean_t iosocket_connect(socket_struct *sockptr, int4 timepar, boolean_t updat
ABS_TIME cur_time, end_time;
struct timeval *sel_time;
mv_stent *mv_zintdev;
- struct addrinfo *remote_ai_ptr, *raw_ai_ptr;
+ struct addrinfo *remote_ai_ptr, *raw_ai_ptr, *local_ai_ptr;
int errcode, real_errno;
char ipaddr[SA_MAXLEN + 1];
- GTM_SOCKLEN_TYPE sockbuflen;
+ char port_buffer[NI_MAXSERV];
+ GTM_SOCKLEN_TYPE sockbuflen, tmp_addrlen;
DBGSOCK((stdout, "socconn: ************* Entering socconn - timepar: %d\n",timepar));
/* check for validity */
@@ -506,8 +509,41 @@ boolean_t iosocket_connect(socket_struct *sockptr, int4 timepar, boolean_t updat
freeaddrinfo(sockptr->remote.ai_head);
sockptr->remote.ai_head = NULL;
}
+ local_ai_ptr = &(sockptr->local.ai);
if (socket_local != sockptr->protocol)
{
+ tmp_addrlen = SIZEOF(struct sockaddr_storage);
+ if (-1 == getsockname(sockptr->sd, SOCKET_LOCAL_ADDR(sockptr), &tmp_addrlen))
+ {
+ save_errno = errno;
+ errptr = (char *)STRERROR(save_errno);
+ errlen = STRLEN(errptr);
+ if (FD_INVALID != sockptr->sd)
+ {
+ close(sockptr->sd); /* Don't leave a dangling socket around */
+ sockptr->sd = FD_INVALID;
+ }
+ SOCKET_FREE(sockptr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, save_errno, errlen, errptr);
+ return FALSE;
+ }
+ local_ai_ptr->ai_addrlen = tmp_addrlen;
+ local_ai_ptr->ai_family = SOCKET_LOCAL_ADDR(sockptr)->sa_family;
+ GETNAMEINFO(SOCKET_LOCAL_ADDR(sockptr), local_ai_ptr->ai_addrlen, ipaddr, SA_MAXLEN, port_buffer,
+ NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST, errcode);
+ if (0 != errcode)
+ {
+ if (FD_INVALID != sockptr->sd)
+ {
+ close(sockptr->sd); /* Don't leave a dangling socket around */
+ sockptr->sd = FD_INVALID;
+ }
+ SOCKET_FREE(sockptr);
+ RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
+ return FALSE;
+ }
+ sockptr->local.port = ATOI(port_buffer);
+ STRNDUP(ipaddr, SA_MAXLEN, sockptr->local.saddr_ip);
GETNAMEINFO(SOCKET_REMOTE_ADDR(sockptr), remote_ai_ptr->ai_addrlen, ipaddr, SA_MAXLEN, NULL, 0
, NI_NUMERICHOST, errcode);
if (0 != errcode)
@@ -517,6 +553,7 @@ boolean_t iosocket_connect(socket_struct *sockptr, int4 timepar, boolean_t updat
close(sockptr->sd); /* Don't leave a dangling socket around */
sockptr->sd = FD_INVALID;
}
+ SOCKET_FREE(sockptr);
RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
return FALSE;
}
@@ -524,7 +561,11 @@ boolean_t iosocket_connect(socket_struct *sockptr, int4 timepar, boolean_t updat
strncpy(&iod->dollar.key[len], sockptr->remote.saddr_ip, DD_BUFLEN - 1 - len);
# ifndef VMS
} else
- {
+ { /* getsockname does not return info for AF_UNIX connected socket so copy from remote side */
+ local_ai_ptr->ai_socktype = sockptr->remote.ai.ai_socktype;
+ local_ai_ptr->ai_addrlen = sockptr->remote.ai.ai_addrlen;
+ local_ai_ptr->ai_protocol = sockptr->remote.ai.ai_protocol;
+ SOCKET_ADDR_COPY(sockptr->local, sockptr->remote.sa, sockptr->remote.ai.ai_addrlen);
STRNCPY_STR(&iod->dollar.key[len], ((struct sockaddr_un *)(sockptr->remote.sa))->sun_path, DD_BUFLEN - len - 1);
# endif
}
diff --git a/sr_port/iosocket_create.c b/sr_port/iosocket_create.c
index e2ba300..708f2e1 100644
--- a/sr_port/iosocket_create.c
+++ b/sr_port/iosocket_create.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -43,7 +43,6 @@
#include "trans_log_name.h"
#endif
-
error_def(ERR_ADDRTOOLONG);
error_def(ERR_GETSOCKNAMERR);
error_def(ERR_GETADDRINFO);
@@ -63,7 +62,7 @@ socket_struct *iosocket_create(char *sockaddr, uint4 bfsize, int file_des, boole
socket_struct *socketptr;
socket_struct *prev_socketptr;
socket_struct *socklist_head;
- boolean_t passive = FALSE;
+ boolean_t passive = FALSE;
unsigned short port;
int ii, save_errno, tmplen, errlen, sockaddrlen;
char temp_addr[SA_MAXLITLEN], protocolstr[6], *adptr;
@@ -80,6 +79,7 @@ socket_struct *iosocket_create(char *sockaddr, uint4 bfsize, int file_des, boole
int af;
int sd;
int errcode;
+ char host_buffer[NI_MAXHOST];
char port_buffer[NI_MAXSERV];
int port_buffer_len;
int colon_cnt, protooffset;
@@ -264,13 +264,14 @@ socket_struct *iosocket_create(char *sockaddr, uint4 bfsize, int file_des, boole
} else
assertpro(socket_tcpip == protocol || socket_local == protocol); /* protocol already checked */
socketptr->state = socket_created;
+ socketptr->howcreated = passive ? creator_listen : creator_connect;
SOCKET_BUFFER_INIT(socketptr, bfsize);
socketptr->passive = passive;
socketptr->moreread_timeout = DEFAULT_MOREREAD_TIMEOUT;
return socketptr;
} else
- { /* socket already setup by inetd */
+ { /* socket already setup by inetd or passed via JOB or LOCAL socket */
SOCKET_ALLOC(socketptr);
socketptr->sd = file_des;
socketptr->temp_sd = FD_INVALID;
@@ -279,48 +280,101 @@ socket_struct *iosocket_create(char *sockaddr, uint4 bfsize, int file_des, boole
if (-1 == getsockname(socketptr->sd, SOCKET_LOCAL_ADDR(socketptr), &tmp_addrlen))
{
save_errno = errno;
- errptr = (char *)STRERROR(save_errno);
- tmplen = STRLEN(errptr);
- SOCKET_FREE(socketptr);
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, save_errno, tmplen, errptr);
- return NULL;
+# if !defined(__linux__) && !defined(VMS)
+ if ((EOPNOTSUPP == save_errno)
+# if defined(_AIX)
+ || (ENOTCONN == save_errno)
+# endif
+# if defined(__sun) || defined(__hpux)
+ || (EINVAL == save_errno)
+# endif
+ )
+ {
+ SOCKET_LOCAL_ADDR(socketptr)->sa_family = AF_UNIX;
+ ((struct sockaddr_un *)SOCKET_LOCAL_ADDR(socketptr))->sun_path[0] = '\0';
+ tmp_addrlen = SIZEOF(struct sockaddr_un);
+ }
+ else
+# endif
+ {
+ errptr = (char *)STRERROR(save_errno);
+ tmplen = STRLEN(errptr);
+ SOCKET_FREE(socketptr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, save_errno, tmplen, errptr);
+ return NULL;
+ }
}
- ai_ptr->ai_addrlen = tmp_addrlen;
- /* extract port information */
- GETNAMEINFO(SOCKET_LOCAL_ADDR(socketptr), tmp_addrlen, NULL, 0, port_buffer,
- NI_MAXSERV, NI_NUMERICSERV, errcode);
- if (0 != errcode)
+# if !defined(VMS)
+ else if (((size_t) (((struct sockaddr *) 0)->sa_data) >= tmp_addrlen)
+ || (0 == SOCKET_LOCAL_ADDR(socketptr)->sa_family))
{
- SOCKET_FREE(socketptr);
- RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
- return NULL;
+ SOCKET_LOCAL_ADDR(socketptr)->sa_family = AF_UNIX;
+ ((struct sockaddr_un *)SOCKET_LOCAL_ADDR(socketptr))->sun_path[0] = '\0';
+ tmp_addrlen = SIZEOF(struct sockaddr_un);
}
- socketptr->local.port = ATOI(port_buffer);
- tmp_addrlen = SIZEOF(struct sockaddr_storage);
- if (-1 == getpeername(socketptr->sd, SOCKET_REMOTE_ADDR(socketptr), &tmp_addrlen))
+ if (AF_UNIX == SOCKET_LOCAL_ADDR(socketptr)->sa_family)
+ protocol = socket_local;
+ else
+# endif
+ protocol = socket_tcpip;
+ ai_ptr->ai_addrlen = tmp_addrlen;
+ ai_ptr->ai_family = SOCKET_LOCAL_ADDR(socketptr)->sa_family;
+ ai_ptr->ai_socktype = SOCK_STREAM;
+ if (socket_tcpip == protocol)
+ { /* extract port information */
+ GETNAMEINFO(SOCKET_LOCAL_ADDR(socketptr), tmp_addrlen, host_buffer, NI_MAXHOST, port_buffer,
+ NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV, errcode);
+ if (0 != errcode)
+ {
+ SOCKET_FREE(socketptr);
+ RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
+ return NULL;
+ }
+ STRNDUP(host_buffer, NI_MAXHOST, socketptr->local.saddr_ip);
+ socketptr->local.port = ATOI(port_buffer);
+ tmp_addrlen = SIZEOF(struct sockaddr_storage);
+ if (-1 == getpeername(socketptr->sd, SOCKET_REMOTE_ADDR(socketptr), &tmp_addrlen))
+ {
+ save_errno = errno;
+ errptr = (char *)STRERROR(save_errno);
+ tmplen = STRLEN(errptr);
+ SOCKET_FREE(socketptr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, save_errno, tmplen, errptr);
+ return NULL;
+ }
+ }
+# if !defined(VMS)
+ else if (socket_local == protocol)
{
- save_errno = errno;
- errptr = (char *)STRERROR(save_errno);
- tmplen = STRLEN(errptr);
- SOCKET_FREE(socketptr);
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, save_errno, tmplen, errptr);
- return NULL;
+ SOCKET_REMOTE_ADDR(socketptr)->sa_family = AF_UNIX;
+ ((struct sockaddr_un *)SOCKET_REMOTE_ADDR(socketptr))->sun_path[0] = '\0';
+ tmp_addrlen = SIZEOF(struct sockaddr_un);
}
+# endif
socketptr->remote.ai.ai_addrlen = tmp_addrlen;
assert(0 != SOCKET_REMOTE_ADDR(socketptr)->sa_family);
- GETNAMEINFO(SOCKET_REMOTE_ADDR(socketptr), socketptr->remote.ai.ai_addrlen, NULL, 0,
- port_buffer, NI_MAXSERV, NI_NUMERICSERV, errcode);
- if (0 != errcode)
+ socketptr->remote.ai.ai_family = SOCKET_REMOTE_ADDR(socketptr)->sa_family;
+ socketptr->remote.ai.ai_socktype = SOCK_STREAM;
+ assert((socket_tcpip != protocol) || (0 != SOCKET_REMOTE_ADDR(socketptr)->sa_family));
+ if (socket_tcpip == protocol)
{
- SOCKET_FREE(socketptr);
- RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
- return NULL;
- }
- socketptr->remote.port = ATOI(port_buffer);
+ GETNAMEINFO(SOCKET_REMOTE_ADDR(socketptr), socketptr->remote.ai.ai_addrlen, host_buffer, NI_MAXHOST,
+ port_buffer, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV, errcode);
+ if (0 != errcode)
+ {
+ SOCKET_FREE(socketptr);
+ RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
+ return NULL;
+ }
+ STRNDUP(host_buffer, NI_MAXHOST, socketptr->remote.saddr_ip);
+ socketptr->remote.port = ATOI(port_buffer);
+ } else
+ assertpro(socket_tcpip == protocol || socket_local == protocol); /* protocol already checked */
socketptr->state = socket_connected;
- socketptr->protocol = socket_tcpip;
+ socketptr->protocol = protocol;
SOCKET_BUFFER_INIT(socketptr, bfsize);
socketptr->passive = passive;
+ socketptr->howcreated = (2 >= file_des) ? creator_principal : creator_passed;
socketptr->moreread_timeout = DEFAULT_MOREREAD_TIMEOUT;
return socketptr;
}
diff --git a/sr_port/iosocket_flush.c b/sr_port/iosocket_flush.c
index 3160184..cb695c7 100644
--- a/sr_port/iosocket_flush.c
+++ b/sr_port/iosocket_flush.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -23,9 +23,11 @@
#include "gt_timer.h"
#include "iosocketdef.h"
+error_def(ERR_CURRSOCKOFR);
+error_def(ERR_NOSOCKETINDEV);
+error_def(ERR_SOCKPASSDATAMIX);
error_def(ERR_SOCKWRITE);
error_def(ERR_TEXT);
-error_def(ERR_CURRSOCKOFR);
void iosocket_flush(io_desc *iod)
{
@@ -43,11 +45,22 @@ void iosocket_flush(io_desc *iod)
dsocketptr = (d_socket_struct *)iod->dev_sp;
socketptr = dsocketptr->socket[dsocketptr->current_socket];
+ if (0 >= dsocketptr->n_socket)
+ {
+# ifndef VMS
+ if (iod == io_std_device.out)
+ ionl_flush(iod);
+ else
+# endif
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
+ return;
+ }
if (dsocketptr->current_socket >= dsocketptr->n_socket)
{
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CURRSOCKOFR, 2, dsocketptr->current_socket, dsocketptr->n_socket);
return;
}
+ ENSURE_DATA_SOCKET(socketptr);
memcpy(iod->dollar.device, "0", SIZEOF("0"));
if ( -1 == setsockopt(socketptr->sd, SOL_SOCKET, TCP_NODELAY, &on, SIZEOF(on)) ||
(-1 == setsockopt(socketptr->sd, SOL_SOCKET, TCP_NODELAY, &off, SIZEOF(off))))
diff --git a/sr_port/iosocket_handle.c b/sr_port/iosocket_handle.c
index f0e0c11..0eff333 100644
--- a/sr_port/iosocket_handle.c
+++ b/sr_port/iosocket_handle.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -45,13 +45,15 @@
int4 iosocket_handle(char *handle, int *len, boolean_t newhandle, d_socket_struct *dsocketptr)
{
boolean_t unique;
- int4 ii, counter = 0, loop_flag = 1;
+ int4 ii, loop_flag = 1;
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
while(loop_flag)
{
if (newhandle)
{
- SPRINTF(handle, "h%ld%d", time((time_t *)0), counter);
+ SPRINTF(handle, "h%ld%03d", time((time_t *)0), ((TREF(socket_handle_counter))++ % 1000));
*len = (short)strlen(handle);
}
ii = 0;
@@ -70,7 +72,6 @@ int4 iosocket_handle(char *handle, int *len, boolean_t newhandle, d_socket_struc
return (unique ? -1 : ii);
if (unique)
return ii;
- counter++;
}
/* it will never reach here */
return -1;
diff --git a/sr_port/iosocket_iocontrol.c b/sr_port/iosocket_iocontrol.c
index 2f5c3e1..8e517a4 100644
--- a/sr_port/iosocket_iocontrol.c
+++ b/sr_port/iosocket_iocontrol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,7 @@
/* iosocket_iocontrol.c */
#include "mdef.h"
+#include "mvalconv.h"
#include "gtm_socket.h"
#include "gtm_inet.h"
@@ -29,6 +30,7 @@
GBLREF spdesc stringpool;
GBLREF io_pair io_curr_device;
+error_def(ERR_EXPR);
error_def(ERR_INVCTLMNE);
/* for iosocket_dlr_zkey */
@@ -37,40 +39,100 @@ error_def(ERR_INVCTLMNE);
#define MAXEVENTLITLEN (SIZEOF(LISTENING)-1)
#define MAXZKEYITEMLEN (MAX_HANDLE_LEN + SA_MAXLITLEN + MAXEVENTLITLEN + 2) /* 1 pipe and a semicolon */
-void iosocket_iocontrol(mstr *d)
+void iosocket_iocontrol(mstr *mn, int4 argcnt, va_list args)
{
- char action[MAX_DEVCTL_LENGTH];
- unsigned short depth; /* serve as depth for LISTEN and timeout for WAIT */
+ char action[MAX_DEVCTL_LENGTH];
+ unsigned short depth;
int length, n, timeout;
+ pid_t pid;
+ mval *arg, *handlesvar = NULL;
- if (0 == d->len)
+ if (0 == mn->len)
return;
- /* The contents of d->addr are passed to us from op_iocontrol. That routine sets up these parms
- * but does not zero terminate the string we are passing to SSCANF. If this is not a complex parm
- * with parens (as is the case with WRITE /WAIT type statements), SSCANF() will get into trouble
- * if the stringpool contains extra junk. For that reason, we now add a null terminator and make
- * sure the argument is not too big to parse into our buffer above.
- */
- assert(d->addr == (char *)stringpool.free); /* Verify string is where we think it is so we don't corrupt something */
- assert(MAX_DEVCTL_LENGTH > d->len);
- assert(IS_IN_STRINGPOOL(d->addr, d->len));
- *(d->addr + d->len) = '\0';
- if (0 == (n = SSCANF(d->addr, "%[^(](%hu)", &action[0], &depth)))
- memcpy(&action[0], d->addr, d->len);
- if (0 == (length = STRLEN(&action[0])))
- return;
- lower_to_upper((uchar_ptr_t)&action[0], (uchar_ptr_t)&action[0], length);
- if (0 == memcmp(&action[0], "LISTEN", length))
+ assert(MAX_DEVCTL_LENGTH > mn->len);
+ lower_to_upper((uchar_ptr_t)action, (uchar_ptr_t)mn->addr, mn->len);
+ length = mn->len;
+ if (0 == memcmp(action, "LISTEN", length))
{
- if (2 > n)
+ if (1 > argcnt)
depth = DEFAULT_LISTEN_DEPTH;
- iosocket_listen(io_curr_device.out, depth);
- } else if (0 == memcmp(&action[0], "WAIT", length))
+ else
+ {
+ arg = va_arg(args, mval *);
+ if ((NULL == arg) || !MV_DEFINED(arg))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_EXPR, 0);
+ return;
+ }
+ depth = MV_FORCE_INTD(arg);
+ }
+ iosocket_listen(io_curr_device.in, depth);
+ } else if (0 == memcmp(action, "WAIT", length))
{
- timeout = depth;
- if (2 > n)
+ if (1 > argcnt)
timeout = NO_M_TIMEOUT;
- iosocket_wait(io_curr_device.out, timeout); /* depth really means timeout here. */
+ else
+ {
+ arg = va_arg(args, mval *);
+ if ((NULL == arg) || !MV_DEFINED(arg))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_EXPR, 0);
+ return;
+ }
+ timeout = MV_FORCE_INTD(arg);
+ }
+ iosocket_wait(io_curr_device.in, timeout);
+# ifndef VMS
+ } else if (0 == memcmp(action, "PASS", length))
+ {
+ n = argcnt;
+ if (1 <= argcnt)
+ {
+ arg = va_arg(args, mval *);
+ n--;
+ if ((NULL != arg) && MV_DEFINED(arg))
+ pid = MV_FORCE_INTD(arg);
+ else
+ pid = -1;
+ }
+ if (2 <= argcnt)
+ {
+ arg = va_arg(args, mval *);
+ n--;
+ if ((NULL != arg) && MV_DEFINED(arg))
+ timeout = MV_FORCE_INTD(arg);
+ else
+ timeout = NO_M_TIMEOUT;
+ }
+ iosocket_pass_local(io_curr_device.out, pid, timeout, n, args);
+ } else if (0 == memcmp(action, "ACCEPT", length))
+ {
+ n = argcnt;
+ if (1 <= argcnt)
+ {
+ handlesvar = va_arg(args, mval *);
+ n--;
+ }
+ if (2 <= argcnt)
+ {
+ arg = va_arg(args, mval *);
+ n--;
+ if ((NULL != arg) && MV_DEFINED(arg))
+ pid = MV_FORCE_INTD(arg);
+ else
+ pid = -1;
+ }
+ if (3 <= argcnt)
+ {
+ arg = va_arg(args, mval *);
+ n--;
+ if ((NULL != arg) && MV_DEFINED(arg))
+ timeout = MV_FORCE_INTD(arg);
+ else
+ timeout = NO_M_TIMEOUT;
+ }
+ iosocket_accept_local(io_curr_device.in, handlesvar, pid, timeout, n, args);
+# endif
} else
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVCTLMNE);
@@ -82,7 +144,7 @@ void iosocket_dlr_device(mstr *d)
io_desc *iod;
int len;
- iod = io_curr_device.out;
+ iod = io_curr_device.in;
len = STRLEN(iod->dollar.device);
/* verify internal buffer has enough space for $DEVICE string value */
assert((int)d->len > len);
@@ -93,17 +155,17 @@ void iosocket_dlr_device(mstr *d)
void iosocket_dlr_key(mstr *d)
{
- io_desc *iod;
- int len;
+ io_desc *iod;
+ int len;
- iod = io_curr_device.out;
- len = STRLEN(iod->dollar.key);
- /* verify internal buffer has enough space for $DEVICE string value */
- assert((int)d->len > len);
+ iod = io_curr_device.in;
+ len = STRLEN(iod->dollar.key);
+ /* verify internal buffer has enough space for $DEVICE string value */
+ assert((int)d->len > len);
if (len > 0)
- memcpy(d->addr, iod->dollar.key, len);
- d->len = len;
- return;
+ memcpy(d->addr, iod->dollar.key, len);
+ d->len = len;
+ return;
}
void iosocket_dlr_zkey(mstr *d)
@@ -115,9 +177,7 @@ void iosocket_dlr_zkey(mstr *d)
d_socket_struct *dsocketptr;
socket_struct *socketptr;
- iod = io_curr_device.out;
- if (gtmsocket != iod->type)
- iod = io_curr_device.in;
+ iod = io_curr_device.in;
assertpro(gtmsocket == iod->type);
dsocketptr = (d_socket_struct *)iod->dev_sp;
zkeyptr = (char *)stringpool.free;
diff --git a/sr_port/iosocket_open.c b/sr_port/iosocket_open.c
index 59e260a..350e5a3 100644
--- a/sr_port/iosocket_open.c
+++ b/sr_port/iosocket_open.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012, 2013 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -27,6 +27,9 @@
#include "iotimer.h"
#include "io_params.h"
#include "iosocketdef.h"
+#ifndef VMS
+#include "iormdef.h"
+#endif
#include "gtm_caseconv.h"
#include "stringpool.h"
#include "gtm_conv.h"
@@ -39,11 +42,13 @@ GBLREF io_pair io_std_device; /* standard device */
GBLREF boolean_t gtm_utf8_mode;
GBLREF int4 gtm_max_sockets;
GBLREF boolean_t dollar_zininterrupt;
+GBLREF UConverter *chset_desc[];
LITREF unsigned char io_params_size[];
LITREF mstr chset_names[];
error_def(ERR_ABNCOMPTINC);
error_def(ERR_ADDRTOOLONG);
+error_def(ERR_CHSETALREADY);
error_def(ERR_DELIMSIZNA);
error_def(ERR_DELIMWIDTH);
error_def(ERR_DEVPARINAP);
@@ -59,6 +64,17 @@ error_def(ERR_ZINTRECURSEIO);
#define ESTABLISHED "ESTABLISHED"
+#ifdef UNICODE_SUPPORTED
+#define CHECK_CHSETALREADY(CURRCHSET) \
+ if ((0 < newdsocket->n_socket) && (chset_idx != CURRCHSET)) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CHSETALREADY, 2, \
+ chset_names[CURRCHSET].len, chset_names[CURRCHSET].addr);
+#define CHECK_CHSETALREADY2(CURRCHSET,NEWCHSET) \
+ if ((0 < newdsocket->n_socket) && (NEWCHSET != CURRCHSET)) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CHSETALREADY, 2, \
+ chset_names[CURRCHSET].len, chset_names[CURRCHSET].addr);
+#endif
+
short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4 timepar)
{
char addr[SA_MAXLITLEN], *errptr, sockaddr[SA_MAXLITLEN],
@@ -78,6 +94,7 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
boolean_t zint_conn_restart = FALSE;
socket_interrupt *sockintr;
mstr chset_mstr;
+ gtm_chset_t default_chset;
boolean_t attach_specified = FALSE,
listen_specified = FALSE,
connect_specified = FALSE,
@@ -91,7 +108,7 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
ichset_specified,
ochset_specified;
unsigned char delimiter_buffer[MAX_N_DELIMITER * (MAX_DELIM_LEN + 1)], zff_buffer[MAX_ZFF_LEN];
- char ioerror, ip[3], tcp[4],
+ char ioerror,
sock_handle[MAX_HANDLE_LEN], delimiter[MAX_DELIM_LEN + 1];
int socketptr_delim_len;
char ipaddr[SA_MAXLEN];
@@ -196,7 +213,8 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
{ /* Only change ipchset if in UTF8 mode */
chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
chset_mstr.len = *(pp->str.addr + p_offset);
- SET_ENCODING(ioptr->ichset, &chset_mstr);
+ SET_ENCODING_VALIDATE(ioptr->ichset, &chset_mstr,
+ CHECK_CHSETALREADY(ioptr->ichset));
ichset_specified = TRUE;
}
);
@@ -207,7 +225,8 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
{ /* Only change ipchset if in UTF8 mode */
chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
chset_mstr.len = *(pp->str.addr + p_offset);
- SET_ENCODING(ioptr->ochset, &chset_mstr);
+ SET_ENCODING_VALIDATE(ioptr->ochset, &chset_mstr,
+ CHECK_CHSETALREADY(ioptr->ochset));
ochset_specified = TRUE;
}
);
@@ -218,7 +237,9 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
{ /* Only change ipchset/opchset if in UTF8 mode */
chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
chset_mstr.len = *(pp->str.addr + p_offset);
- SET_ENCODING(ioptr->ichset, &chset_mstr);
+ SET_ENCODING_VALIDATE(ioptr->ichset, &chset_mstr,
+ CHECK_CHSETALREADY(ioptr->ichset));
+ CHECK_CHSETALREADY2(ioptr->ochset, ioptr->ichset);
ioptr->ochset = ioptr->ichset;
ichset_specified = ochset_specified = TRUE;
}
@@ -229,6 +250,8 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
*/
case iop_m:
UNICODE_ONLY(
+ CHECK_CHSETALREADY2(ioptr->ichset, CHSET_M);
+ CHECK_CHSETALREADY2(ioptr->ochset, CHSET_M);
ioptr->ichset = ioptr->ochset = CHSET_M;
ichset_specified = ochset_specified = TRUE;
);
@@ -237,6 +260,8 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
UNICODE_ONLY(
if (gtm_utf8_mode)
{ /* Only change chset if in UTF8 mode */
+ CHECK_CHSETALREADY2(ioptr->ichset, CHSET_UTF16);
+ CHECK_CHSETALREADY2(ioptr->ochset, CHSET_UTF16);
ioptr->ichset = ioptr->ochset = CHSET_UTF16;
ichset_specified = ochset_specified = TRUE;
}
@@ -246,6 +271,8 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
UNICODE_ONLY(
if (gtm_utf8_mode)
{ /* Only change chset if in UTF8 mode */
+ CHECK_CHSETALREADY2(ioptr->ichset, CHSET_UTF16BE);
+ CHECK_CHSETALREADY2(ioptr->ochset, CHSET_UTF16BE);
ioptr->ichset = ioptr->ochset = CHSET_UTF16BE;
ichset_specified = ochset_specified = TRUE;
}
@@ -255,6 +282,8 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
UNICODE_ONLY(
if (gtm_utf8_mode)
{ /* Only change chset if in UTF8 mode */
+ CHECK_CHSETALREADY2(ioptr->ichset, CHSET_UTF16LE);
+ CHECK_CHSETALREADY2(ioptr->ochset, CHSET_UTF16LE);
ioptr->ichset = ioptr->ochset = CHSET_UTF16LE;
ichset_specified = ochset_specified = TRUE;
}
@@ -308,7 +337,7 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
ioerror = *(pp->str.addr + p_offset + 1); /* the first char decides */
break;
case iop_exception:
- ioptr->error_handler.len = *(pp->str.addr + p_offset);
+ ioptr->error_handler.len = (int)(*(pp->str.addr + p_offset));
ioptr->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
s2pool(&ioptr->error_handler);
break;
@@ -392,14 +421,6 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
}
- if (!ichset_specified)
- ioptr->ichset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M;
- if (!ochset_specified)
- ioptr->ochset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M;
- if (CHSET_M != ioptr->ichset && CHSET_UTF16 != ioptr->ichset)
- get_chset_desc(&chset_names[ioptr->ichset]);
- if (CHSET_M != ioptr->ochset && CHSET_UTF16 != ioptr->ochset)
- get_chset_desc(&chset_names[ioptr->ochset]);
if (listen_specified && connect_specified)
{
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ABNCOMPTINC, 6, LEN_AND_LIT("CONNECT"),
@@ -488,7 +509,13 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
}
if (NULL == socketptr->zff.addr) /* we rely on socketptr->zff.addr being set to 0 in iosocket_create() */
socketptr->zff.addr = (char *)malloc(MAX_ZFF_LEN);
+ else if (socketptr->zff.addr != socketptr->ozff.addr)
+ {
+ assert(NULL != socketptr->ozff.addr);
+ free(socketptr->ozff.addr); /* prevent leak of prior converted form */
+ }
memcpy(socketptr->zff.addr, zff_buffer, zff_len);
+ socketptr->ozff = socketptr->zff; /* will contain converted UTF-16 form if needed */
}
}
/* action */
@@ -501,36 +528,53 @@ short iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4
SOCKET_FREE(socketptr);
return FALSE;
} else if (is_principal)
- { /* fill in what bind or connect would */
- ai_ptr = &(socketptr->local.ai);
- remote_ai_ptr = &(socketptr->remote.ai);
- /* translate internal address to numeric ip address */
- GETNAMEINFO(SOCKET_LOCAL_ADDR(socketptr), ai_ptr->ai_addrlen, ipaddr, SIZEOF(ipaddr), NULL, 0, NI_NUMERICHOST,
- errcode);
- if (0 != errcode)
- {
- RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
- return FALSE;
- }
- STRNDUP(ipaddr, SIZEOF(ipaddr), socketptr->local.saddr_ip);
- GETNAMEINFO(SOCKET_REMOTE_ADDR(socketptr), remote_ai_ptr->ai_addrlen, ipaddr, SIZEOF(ipaddr), NULL, 0,
- NI_NUMERICHOST, errcode);
- if (0 != errcode)
- {
- RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
- return FALSE;
- }
- STRNDUP(ipaddr, SIZEOF(ipaddr), socketptr->remote.saddr_ip);
+ {
len = SIZEOF(ESTABLISHED) - 1;
memcpy(&ioptr->dollar.key[0], ESTABLISHED, len);
ioptr->dollar.key[len++] = '|';
memcpy(&ioptr->dollar.key[len], socketptr->handle, socketptr->handle_len);
len += socketptr->handle_len;
ioptr->dollar.key[len++] = '|';
- strncpy(&ioptr->dollar.key[len], socketptr->remote.saddr_ip, DD_BUFLEN - 1 - len);
+ if (socket_tcpip == socketptr->protocol)
+ strncpy(&ioptr->dollar.key[len], socketptr->remote.saddr_ip, DD_BUFLEN - 1 - len);
+# ifndef VMS
+ else if (socket_local == socketptr->protocol)
+ {
+ if ((NULL != socketptr->local.sa)
+ && (NULL != ((struct sockaddr_un *)(socketptr->local.sa))->sun_path))
+ strncpy(&ioptr->dollar.key[len], ((struct sockaddr_un *)(socketptr->local.sa))->sun_path,
+ DD_BUFLEN - 1 - len);
+ else if ((NULL != socketptr->remote.sa)
+ && (NULL != ((struct sockaddr_un *)(socketptr->remote.sa))->sun_path))
+ strncpy(&ioptr->dollar.key[len], ((struct sockaddr_un *)(socketptr->remote.sa))->sun_path,
+ DD_BUFLEN - 1 - len);
+ /* set default delimiter on principal local sockets to resemble rm device */
+ delimiter_buffer[0] = NATIVE_NL;
+ delimiter_len = 1;
+ iosocket_delimiter(delimiter_buffer, delimiter_len, socketptr, FALSE);
+ }
+# endif
+ else
+ ioptr->dollar.key[len] = '\0';
ioptr->dollar.key[DD_BUFLEN-1] = '\0'; /* In case we fill the buffer */
}
/* commit the changes to the list */
+ if (0 >= dsocketptr->n_socket) /* before any new socket added */
+ { /* don't change chset if this is not the first socket */
+ default_chset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M;
+ if (!ichset_specified && !IS_UTF16_CHSET(ioptr->ichset))
+ ioptr->ichset = default_chset;
+ if (!ochset_specified && !IS_UTF16_CHSET(ioptr->ochset))
+ ioptr->ochset = default_chset;
+ if (CHSET_M != ioptr->ichset && CHSET_UTF16 != ioptr->ichset)
+ get_chset_desc(&chset_names[ioptr->ichset]);
+ if (CHSET_M != ioptr->ochset && CHSET_UTF16 != ioptr->ochset)
+ get_chset_desc(&chset_names[ioptr->ochset]);
+ if (ichset_specified)
+ newdsocket->ichset_specified = TRUE;
+ if (ochset_specified)
+ newdsocket->ochset_specified = TRUE;
+ }
if (listen_specified || connect_specified || is_principal)
{
socketptr->dev = dsocketptr;
diff --git a/sr_port/iosocket_readfl.c b/sr_port/iosocket_readfl.c
index 8aa9066..d1e1fdf 100644
--- a/sr_port/iosocket_readfl.c
+++ b/sr_port/iosocket_readfl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -65,6 +65,7 @@ error_def(ERR_IOEOF);
error_def(ERR_MAXSTRLEN);
error_def(ERR_NOSOCKETINDEV);
error_def(ERR_SETSOCKOPTERR);
+error_def(ERR_SOCKPASSDATAMIX);
error_def(ERR_STACKCRIT);
error_def(ERR_STACKOFLOW);
error_def(ERR_TEXT);
@@ -124,7 +125,7 @@ void iosocket_readfl_badchar(mval *vmvalptr, int datalen, int delimlen, unsigned
int iosocket_readfl(mval *v, int4 width, int4 timeout)
{
int ret, byteperchar;
- boolean_t timed, vari, more_data, terminator, has_delimiter, requeue_done;
+ boolean_t timed, vari, more_data, terminator, has_delimiter, requeue_done, do_delim_conv, need_get_chset;
boolean_t zint_restart, outofband_terminate, one_read_done, utf8_active;
int flags, len, real_errno, save_errno, fcntl_res, errlen, charlen, stp_need;
int bytes_read, orig_bytes_read, ii, max_bufflen, bufflen, chars_read, mb_len, match_delim;
@@ -153,9 +154,18 @@ int iosocket_readfl(mval *v, int4 width, int4 timeout)
dsocketptr = (d_socket_struct *)(iod->dev_sp);
if (0 >= dsocketptr->n_socket)
{
- iod->dollar.za = 9;
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
- return 0;
+# ifndef VMS
+ if (iod == io_std_device.in)
+ return ionl_readfl(v, width, timeout);
+ else
+ {
+# endif
+ iod->dollar.za = 9;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
+ return 0;
+# ifndef VMS
+ }
+# endif
}
if (dsocketptr->n_socket <= dsocketptr->current_socket)
{
@@ -179,6 +189,7 @@ int iosocket_readfl(mval *v, int4 width, int4 timeout)
*/
socketptr = dsocketptr->socket[dsocketptr->current_socket];
assert(socketptr);
+ ENSURE_DATA_SOCKET(socketptr);
sockintr = &dsocketptr->sock_save_state;
assert(sockintr);
outofband_terminate = FALSE;
@@ -306,6 +317,13 @@ int iosocket_readfl(mval *v, int4 width, int4 timeout)
socketptr->lastop = TCP_READ;
ret = TRUE;
has_delimiter = (0 < socketptr->n_delimiter);
+ do_delim_conv = FALSE;
+ if (has_delimiter && IS_UTF16_CHSET(iod->ichset))
+ {
+ if (socketptr->delimiter[0].addr == socketptr->idelimiter[0].addr)
+ do_delim_conv = TRUE;
+ }
+ need_get_chset = FALSE; /* if we change ichset, make sure converter available */
time_for_read.at_sec = 0;
if (0 == timeout)
time_for_read.at_usec = 0;
@@ -547,6 +565,7 @@ int iosocket_readfl(mval *v, int4 width, int4 timeout)
} else
{
iod->ichset = ichset = CHSET_UTF16BE;
+ need_get_chset = TRUE;
bytes_read -= UTF16BE_BOM_LEN; /* Throw way BOM */
DBGSOCK2((stdout, "socrfl: UTF16BE BOM detected\n"));
}
@@ -563,6 +582,7 @@ int iosocket_readfl(mval *v, int4 width, int4 timeout)
} else
{
iod->ichset = ichset = CHSET_UTF16LE;
+ need_get_chset = TRUE;
bytes_read -= UTF16BE_BOM_LEN; /* Throw away BOM */
DBGSOCK2((stdout, "socrfl: UTF16LE BOM detected\n"));
}
@@ -574,6 +594,7 @@ int iosocket_readfl(mval *v, int4 width, int4 timeout)
{
DBGSOCK2((stdout, "socrfl: UTF16BE BOM assumed\n"));
iod->ichset = ichset = CHSET_UTF16BE;
+ need_get_chset = TRUE;
}
}
} else
@@ -584,6 +605,7 @@ int iosocket_readfl(mval *v, int4 width, int4 timeout)
{
DBGSOCK2((stdout, "socrfl: UTF16BE BOM assumed\n"));
iod->ichset = ichset = CHSET_UTF16BE;
+ need_get_chset = TRUE;
}
}
} else
@@ -594,16 +616,18 @@ int iosocket_readfl(mval *v, int4 width, int4 timeout)
DBGSOCK2((stdout, "socrfl: UTF8 BOM detected/ignored\n"));
}
}
+ socketptr->first_read = FALSE;
+ } else if (socketptr->first_read)
+ socketptr->first_read = FALSE;
+ if (need_get_chset)
+ {
+ get_chset_desc(&chset_names[ichset]);
+ need_get_chset = FALSE;
}
- if (socketptr->first_read)
+ if (do_delim_conv)
{
- if ((CHSET_UTF16BE == ichset) || (CHSET_UTF16LE == ichset))
- {
- get_chset_desc(&chset_names[ichset]);
- if (has_delimiter)
- iosocket_delim_conv(socketptr, ichset);
- }
- socketptr->first_read = FALSE;
+ iosocket_delim_conv(socketptr, ichset);
+ do_delim_conv = FALSE;
}
if (bytes_read && has_delimiter)
{ /* Check to see if it is a delimiter */
diff --git a/sr_port/iosocket_use.c b/sr_port/iosocket_use.c
index 5ab5d0d..2ed9c33 100644
--- a/sr_port/iosocket_use.c
+++ b/sr_port/iosocket_use.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -45,6 +45,7 @@ GBLREF boolean_t dollar_zininterrupt;
LITREF nametabent filter_names[];
LITREF unsigned char filter_index[27];
LITREF unsigned char io_params_size[];
+LITREF mstr chset_names[];
error_def(ERR_ABNCOMPTINC);
error_def(ERR_ACOMPTBINC);
@@ -69,13 +70,13 @@ error_def(ERR_ZINTRECURSEIO);
void iosocket_use(io_desc *iod, mval *pp)
{
unsigned char ch, len;
- int handled_len, handlea_len, handles_len;
+ int handled_len, handlea_len, handles_len, int_len;
int4 length, width, new_len;
d_socket_struct *dsocketptr;
socket_struct *socketptr, newsocket;
char handlea[MAX_HANDLE_LEN], handles[MAX_HANDLE_LEN], handled[MAX_HANDLE_LEN];
char addr[SA_MAXLITLEN], *errptr, sockaddr[SA_MAXLITLEN],
- temp_addr[SA_MAXLITLEN], ioerror;
+ temp_addr[SA_MAXLITLEN], ioerror, *free_ozff = NULL;
unsigned char delimiter_buffer[MAX_N_DELIMITER * (MAX_DELIM_LEN + 1)];
unsigned char zff_buffer[MAX_ZFF_LEN];
boolean_t attach_specified = FALSE,
@@ -96,7 +97,6 @@ void iosocket_use(io_desc *iod, mval *pp)
char *tab;
int save_errno;
size_t d_socket_struct_len;
- mstr lcl_zff;
assert(iod->state == dev_open);
assert(iod->type == gtmsocket);
@@ -134,7 +134,7 @@ void iosocket_use(io_desc *iod, mval *pp)
switch (ch)
{
case iop_exception:
- iod->error_handler.len = *(pp->str.addr + p_offset);
+ iod->error_handler.len = (int)(*(pp->str.addr + p_offset));
iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
s2pool(&iod->error_handler);
break;
@@ -180,14 +180,14 @@ void iosocket_use(io_desc *iod, mval *pp)
case iop_connect:
n_specified++;
connect_specified = TRUE;
- len = *(pp->str.addr + p_offset);
- if (len < USR_SA_MAXLITLEN)
+ int_len = (int)(*(pp->str.addr + p_offset));
+ if (int_len < USR_SA_MAXLITLEN)
{
- memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), len);
- sockaddr[len] = '\0';
+ memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), int_len);
+ sockaddr[int_len] = '\0';
} else
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ADDRTOOLONG,
- 4, len, pp->str.addr + p_offset + 1, len, USR_SA_MAXLITLEN);
+ 4, int_len, pp->str.addr + p_offset + 1, int_len, USR_SA_MAXLITLEN);
break;
case iop_delimiter:
n_specified++;
@@ -226,14 +226,14 @@ void iosocket_use(io_desc *iod, mval *pp)
case iop_zlisten:
n_specified++;
listen_specified = TRUE;
- len = *(pp->str.addr + p_offset);
- if (len < USR_SA_MAXLITLEN)
+ int_len = (int)(*(pp->str.addr + p_offset));
+ if (int_len < USR_SA_MAXLITLEN)
{
- memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), len);
- sockaddr[len] = '\0';
+ memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), int_len);
+ sockaddr[int_len] = '\0';
} else
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ADDRTOOLONG,
- 4, len, pp->str.addr + p_offset + 1, len, USR_SA_MAXLITLEN);
+ 4, int_len, pp->str.addr + p_offset + 1, int_len, USR_SA_MAXLITLEN);
break;
case iop_socket:
n_specified++;
@@ -386,6 +386,14 @@ void iosocket_use(io_desc *iod, mval *pp)
/* allocate the structure for a new socket */
if (NULL == (socketptr = iosocket_create(sockaddr, bfsize, -1, listen_specified)))
return;
+ if (gtm_max_sockets <= newdsocket->n_socket)
+ {
+ if (FD_INVALID != socketptr->temp_sd)
+ close(socketptr->temp_sd);
+ SOCKET_FREE(socketptr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
+ return;
+ }
/* give the new socket a handle */
iosocket_handle(handles, &handles_len, TRUE, dsocketptr);
socketptr->handle_len = handles_len;
@@ -419,7 +427,12 @@ void iosocket_use(io_desc *iod, mval *pp)
{
if (0 >= newdsocket->n_socket)
{
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
+# ifndef VMS
+ if (iod == io_std_device.out)
+ ionl_use(iod, pp);
+ else
+# endif
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
return;
}
if (newdsocket->n_socket <= newdsocket->current_socket)
@@ -438,77 +451,35 @@ void iosocket_use(io_desc *iod, mval *pp)
if (0 <= delimiter_len)
{
iosocket_delimiter(delimiter_buffer, delimiter_len, &newsocket, (0 == delimiter_len));
- /* The delimiter has changed. The iosocket_readfl/write routine won't notice so we have to do
- the UTF16xx conversion since we changed it.
- */
- DBGSOCK2((stdout, "socuse: Delimiter(s) replaced - num delims: %d delimiter_len: %d ichset: %d ochset: %d\n",
- newsocket.n_delimiter, delimiter_len, iod->ichset, iod->ochset));
- if (0 < delimiter_len)
- {
- if (!newsocket.first_read && (CHSET_UTF16BE == iod->ichset || CHSET_UTF16LE == iod->ichset))
- { /* We have been reading with this socket so convert this new delimiter set */
- DBGSOCK2((stdout, "socuse: Converting new delimiters for input\n"));
- iosocket_delim_conv(&newsocket, iod->ichset);
- }
- if (!newsocket.first_write && (CHSET_UTF16BE == iod->ochset || CHSET_UTF16LE == iod->ochset))
- { /* We have been writing with this socket so convert the new default output delimiter */
- DBGSOCK2((stdout, "socuse: Converting new delimiters for output\n"));
- if (newsocket.first_read || (CHSET_UTF16BE != iod->ichset && CHSET_UTF16LE != iod->ichset))
- { /* Need to do conversion as iosocket_delim_conv above didn't do it for us */
- DBGSOCK2((stdout, "socuse: running convert for write since input didn't do it\n"));
- new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset],
- &newsocket.delimiter[0], NULL, NULL);
- if (MAX_DELIM_LEN < new_len)
- {
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DELIMSIZNA);
- return;
- }
- } else
- {
- DBGSOCK2((stdout, "socuse: using previous length from read conversion\n"));
- new_len = newsocket.idelimiter[0].len;
- }
- newsocket.odelimiter0.len = new_len;
- UNICODE_ONLY(newsocket.odelimiter0.char_len = newsocket.delimiter[0].char_len);
- newsocket.odelimiter0.addr = malloc(new_len);
- memcpy(newsocket.odelimiter0.addr,
- (newsocket.first_read ? (char *)stringpool.free : newsocket.idelimiter[0].addr),
- new_len);
- }
- }
+ socketptr->n_delimiter = 0; /* prevent double frees if error */
}
if (iod->wrap && 0 != newsocket.n_delimiter && iod->width < newsocket.delimiter[0].len)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DELIMWIDTH, 2, iod->width, newsocket.delimiter[0].len);
if (0 <= zff_len && /* ZFF or ZNOFF specified */
0 < (newsocket.zff.len = zff_len)) /* assign the new ZFF len, might be 0 from ZNOFF, or ZFF="" */
{ /* ZFF="non-zero-len-string" specified */
- if (CHSET_UTF16BE == iod->ochset || CHSET_UTF16LE == iod->ochset) /* need conversion of ZFF */
+ if (gtm_utf8_mode) /* Check if ZFF has any invalid UTF-8 character */
+ { /* Note: the ZFF string originates from the source program, so is in UTF-8 mode or M mode
+ regardless of OCHSET of this device. ZFF is output on WRITE # command, and MUST contain
+ valid UTF-8 sequence.
+ */
+ utf8_len_strict(zff_buffer, zff_len);
+ }
+ if ((NULL != newsocket.ozff.addr) && (socketptr->ozff.addr != socketptr->zff.addr))
+ free_ozff = newsocket.ozff.addr; /* previously converted */
+ if (NULL == newsocket.zff.addr) /* we rely on newsocket.zff.addr being set to 0 in iosocket_create() */
{
- DBGSOCK2((stdout, "socuse: Converting zff\n"));
- lcl_zff.addr = (char *)zff_buffer;
- lcl_zff.len = zff_len;
- new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset], &lcl_zff, NULL, NULL);
- if (MAX_ZFF_LEN < new_len)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZFF2MANY, 2, new_len, MAX_ZFF_LEN);
- if (NULL == newsocket.zff.addr) /* we rely on newsocket.zff.addr being set to 0 in iosocket_create() */
- newsocket.zff.addr = (char *)malloc(MAX_ZFF_LEN);
- newsocket.zff.len = new_len;
- UNICODE_ONLY(newsocket.zff.char_len = 0); /* don't care */
- memcpy(newsocket.zff.addr, stringpool.free, new_len);
-
- } else
- { /* Store parm without conversion */
- if (gtm_utf8_mode) /* Check if ZFF has any invalid UTF-8 character */
- { /* Note: the ZFF string originates from the source program, so is in UTF-8 mode or M mode
- regardless of OCHSET of this device. ZFF is output on WRITE # command, and MUST contain
- valid UTF-8 sequence. This validation is handled by gtm_conv in the path above.
- */
- utf8_len_strict(zff_buffer, zff_len);
- }
- if (NULL == newsocket.zff.addr) /* we rely on newsocket.zff.addr being set to 0 in iosocket_create() */
- newsocket.zff.addr = (char *)malloc(MAX_ZFF_LEN);
- memcpy(newsocket.zff.addr, zff_buffer, zff_len);
+ socketptr->zff.addr = newsocket.zff.addr = (char *)malloc(MAX_ZFF_LEN);
+ socketptr->zff.len = zff_len; /* in case error so SOCKET_FREE frees */
}
+ memcpy(newsocket.zff.addr, zff_buffer, zff_len);
+ newsocket.ozff = newsocket.zff;
+ } else if (0 == zff_len)
+ {
+ if ((NULL != newsocket.ozff.addr) && (socketptr->ozff.addr != socketptr->zff.addr))
+ free_ozff = newsocket.ozff.addr; /* previously converted */
+ newsocket.ozff = newsocket.zff;
+
}
if (ioerror_specified)
newsocket.ioerror = ('T' == ioerror || 't' == ioerror);
@@ -527,16 +498,19 @@ void iosocket_use(io_desc *iod, mval *pp)
if (bfsize_specified)
newsocket.buffer_size = bfsize;
#ifdef TCP_NODELAY
- nodelay = newsocket.nodelay ? 1 : 0;
- if ((socketptr->nodelay != newsocket.nodelay) &&
- (-1 == setsockopt(newsocket.sd, IPPROTO_TCP,
- TCP_NODELAY, &nodelay, SIZEOF(nodelay))))
+ if (socket_local != newsocket.protocol)
{
- save_errno = errno;
- errptr = (char *)STRERROR(save_errno);
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("TCP_NODELAY"), save_errno,
- LEN_AND_STR(errptr));
- return;
+ nodelay = newsocket.nodelay ? 1 : 0;
+ if ((socketptr->nodelay != newsocket.nodelay) &&
+ (-1 == setsockopt(newsocket.sd, IPPROTO_TCP,
+ TCP_NODELAY, &nodelay, SIZEOF(nodelay))))
+ {
+ save_errno = errno;
+ errptr = (char *)STRERROR(save_errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("TCP_NODELAY"),
+ save_errno, LEN_AND_STR(errptr));
+ return;
+ }
}
#endif
if ((socketptr->bufsiz != newsocket.bufsiz) &&
@@ -575,18 +549,18 @@ void iosocket_use(io_desc *iod, mval *pp)
/* ------------------------------------ commit changes -------------------------------------- */
if (create_new_socket)
{
- if (gtm_max_sockets <= newdsocket->n_socket)
- {
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
- return;
- }
/* a new socket is created. so add to the list */
newsocket.dev = dsocketptr;
newdsocket->socket[newdsocket->n_socket++] = socketptr;
newdsocket->current_socket = newdsocket->n_socket - 1;
}
- else if (socketptr->buffer_size != newsocket.buffer_size)
- free(socketptr->buffer);
+ else
+ {
+ if (NULL != free_ozff)
+ free(free_ozff);
+ if (socketptr->buffer_size != newsocket.buffer_size)
+ free(socketptr->buffer);
+ }
*socketptr = newsocket;
memcpy(dsocketptr, newdsocket, d_socket_struct_len);
return;
diff --git a/sr_port/iosocket_wait.c b/sr_port/iosocket_wait.c
index 4ae6883..2ca1921 100644
--- a/sr_port/iosocket_wait.c
+++ b/sr_port/iosocket_wait.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,6 +24,7 @@
#include "gtm_inet.h"
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtm_unistd.h"
#ifdef USE_POLL
#include <sys/poll.h>
#endif
@@ -57,6 +58,7 @@ GBLREF mv_stent *mv_chain;
GBLREF int dollar_truth;
error_def(ERR_GETNAMEINFO);
+error_def(ERR_GETSOCKNAMERR);
error_def(ERR_SOCKACPT);
error_def(ERR_SOCKWAIT);
error_def(ERR_TEXT);
@@ -67,7 +69,7 @@ error_def(ERR_STACKOFLOW);
boolean_t iosocket_wait(io_desc *iod, int4 timepar)
{
- struct timeval utimeout;
+ struct timeval utimeout, *utimeoutptr;
ABS_TIME cur_time, end_time;
#ifdef USE_POLL
nfds_t poll_nfds;
@@ -81,7 +83,7 @@ boolean_t iosocket_wait(io_desc *iod, int4 timepar)
fd_set select_fdset;
#endif
d_socket_struct *dsocketptr;
- socket_struct *socketptr, *newsocketptr;
+ socket_struct *socketptr;
socket_interrupt *sockintr;
char *errptr, *charptr;
int4 errlen, ii, jj, msec_timeout;
@@ -234,13 +236,22 @@ boolean_t iosocket_wait(io_desc *iod, int4 timepar)
for ( ; ; )
{
#ifdef USE_POLL
- poll_timeout = (utimeout.tv_sec * 1000) + (utimeout.tv_usec / 1000);
+ if ((0 < rconnected) || (0 <rlisten))
+ poll_timeout = 0;
+ else if (NO_M_TIMEOUT == timepar)
+ poll_timeout = -1;
+ else
+ poll_timeout = (utimeout.tv_sec * 1000) + (utimeout.tv_usec / 1000);
poll_fd = -1;
rv = poll(poll_fds, poll_nfds, poll_timeout);
#endif
#ifdef USE_SELECT
- rv = select(select_max_fd + 1, (void *)&select_fdset, (void *)0, (void *)0,
- (timepar == NO_M_TIMEOUT ? (struct timeval *)NULL : &utimeout));
+ utimeoutptr = &utimeout;
+ if ((0 < rconnected) || (0 <rlisten))
+ utimeout.tv_sec = utimeout.tv_usec = 0;
+ else if (NO_M_TIMEOUT == timepar)
+ utimeoutptr = (struct timeval *)NULL;
+ rv = select(select_max_fd + 1, (void *)&select_fdset, (void *)0, (void *)0, utimeoutptr);
#endif
if (0 > rv && EINTR == errno)
{
@@ -301,14 +312,19 @@ boolean_t iosocket_wait(io_desc *iod, int4 timepar)
/* find out which sockets are ready */
oldestlistencycle = oldestconnectedcycle = oldesteventcycle = 0;
oldestlistenindex = oldestconnectedindex = oldesteventindex = -1;
- for (ii = jj = 0; ii < dsocketptr->n_socket; ii++)
+ for (ii = 0; ii < dsocketptr->n_socket; ii++)
{
socketptr = dsocketptr->socket[ii];
if ((socket_listening != socketptr->state) && (socket_connected != socketptr->state))
continue; /* not a candidate for /WAIT */
#ifdef USE_POLL
- assertpro((0 == jj) || (jj <= poll_nfds)); /* equal after last polled fd checked */
- if (nselect && (socketptr->sd == poll_fds[jj].fd) && (poll_fds[jj++].revents & POLLIN))
+ for (jj = 0; jj < poll_nfds; jj++)
+ {
+ if (socketptr == poll_socketptr[jj])
+ break;
+ }
+ assertpro((0 == jj) || (jj <= poll_nfds)); /* equal poll_nfds if not polled */
+ if (nselect && (jj != poll_nfds) && (socketptr->sd == poll_fds[jj].fd) && (poll_fds[jj].revents & POLLIN))
#endif
#ifdef USE_SELECT
assertpro(FD_SETSIZE > socketptr->sd);
@@ -387,7 +403,12 @@ boolean_t iosocket_wait(io_desc *iod, int4 timepar)
} else
{
assertpro(socket_local == socketptr->protocol);
- charptr = ((struct sockaddr_un *)(socketptr->local.sa))->sun_path;
+ if (NULL != socketptr->local.sa)
+ charptr = ((struct sockaddr_un *)(socketptr->local.sa))->sun_path;
+ else if (NULL != socketptr->remote.sa)
+ charptr = ((struct sockaddr_un *)(socketptr->remote.sa))->sun_path;
+ else
+ charptr = (char *)"";
strncpy(&dsocketptr->iod->dollar.key[len], charptr, DD_BUFLEN - len - 1);
# endif
}
@@ -404,7 +425,7 @@ int iosocket_accept(d_socket_struct *dsocketptr, socket_struct *socketptr, boole
{
char *errptr;
int4 errlen;
- int rv, len, errcode;
+ int rv, len, errcode, save_errno;
char port_buffer[NI_MAXSERV], ipaddr[SA_MAXLEN + 1];
#ifdef USE_POLL
struct pollfd poll_fds;
@@ -414,7 +435,7 @@ int iosocket_accept(d_socket_struct *dsocketptr, socket_struct *socketptr, boole
fd_set select_fdset;
#endif
struct timeval utimeout;
- GTM_SOCKLEN_TYPE size;
+ GTM_SOCKLEN_TYPE size, addrlen;
socket_struct *newsocketptr;
struct sockaddr_storage peer; /* socket address + port */
struct sockaddr *peer_sa_ptr;
@@ -470,13 +491,18 @@ int iosocket_accept(d_socket_struct *dsocketptr, socket_struct *socketptr, boole
}
}
SOCKET_DUP(socketptr, newsocketptr);
+ newsocketptr->remote.ai.ai_socktype = socketptr->local.ai.ai_socktype;
+ newsocketptr->remote.ai.ai_protocol = socketptr->local.ai.ai_protocol;
+ newsocketptr->lastaction = newsocketptr->readycycle = 0;
+ newsocketptr->pendingevent = FALSE;
newsocketptr->sd = rv;
if (socket_local != newsocketptr->protocol)
{ /* translate internal address to numeric ip address */
SOCKET_ADDR_COPY(newsocketptr->remote, peer_sa_ptr, size); /* info not set for socket_local */
- if (0 != (errcode = getnameinfo(peer_sa_ptr, size, ipaddr, SA_MAXLEN,
- NULL, 0, NI_NUMERICHOST)))
+ GETNAMEINFO(peer_sa_ptr, size, ipaddr, SA_MAXLEN, NULL, 0, NI_NUMERICHOST, errcode);
+ if (0 != errcode)
{
+ close(newsocketptr->sd);
SOCKET_FREE(newsocketptr);
RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
return -1;
@@ -488,17 +514,46 @@ int iosocket_accept(d_socket_struct *dsocketptr, socket_struct *socketptr, boole
GETNAMEINFO(peer_sa_ptr, size, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV, errcode);
if (0 != errcode)
{
+ close(newsocketptr->sd);
SOCKET_FREE(newsocketptr);
RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
return -1;
}
newsocketptr->remote.port = ATOI(port_buffer);
+ newsocketptr->remote.ai.ai_addrlen = size;
+ addrlen = SIZEOF(struct sockaddr_storage);
+ if (-1 == getsockname(newsocketptr->sd, SOCKET_LOCAL_ADDR(newsocketptr), &addrlen))
+ {
+ save_errno = errno;
+ errptr = (char *)STRERROR(save_errno);
+ errlen = STRLEN(errptr);
+ close(newsocketptr->sd);
+ SOCKET_FREE(newsocketptr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, save_errno, errlen, errptr);
+ return -1;
+ }
+ newsocketptr->local.ai.ai_addrlen = addrlen;
+ newsocketptr->local.ai.ai_family = SOCKET_LOCAL_ADDR(newsocketptr)->sa_family;
+ GETNAMEINFO(SOCKET_LOCAL_ADDR(newsocketptr), newsocketptr->local.ai.ai_addrlen, ipaddr,
+ SA_MAXLEN, NULL, 0, NI_NUMERICHOST, errcode);
+ if (0 != errcode)
+ {
+ close(newsocketptr->sd);
+ SOCKET_FREE(newsocketptr);
+ RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
+ return -1;
+ }
+ if (NULL != newsocketptr->local.saddr_ip)
+ free(newsocketptr->local.saddr_ip);
+ STRNDUP(ipaddr, SA_MAXLEN, newsocketptr->local.saddr_ip);
}
newsocketptr->state = socket_connected;
newsocketptr->passive = FALSE;
+ newsocketptr->howcreated = creator_accept;
newsocketptr->first_read = newsocketptr->first_write = TRUE;
/* put the new-born socket to the list and create a handle for it */
iosocket_handle(newsocketptr->handle, &newsocketptr->handle_len, TRUE, dsocketptr);
+ STRNDUP(socketptr->handle, socketptr->handle_len, newsocketptr->parenthandle);
socketptr->lastaction = dsocketptr->waitcycle; /* record cycle for last connect */
dsocketptr->socket[dsocketptr->n_socket++] = newsocketptr;
dsocketptr->current_socket = dsocketptr->n_socket - 1;
@@ -513,11 +568,14 @@ int iosocket_accept(d_socket_struct *dsocketptr, socket_struct *socketptr, boole
# ifndef VMS
else
{ /* get path from listening socket local side */
+ assert(NULL != socketptr->local.sa);
STRNCPY_STR(&dsocketptr->iod->dollar.key[len], ((struct sockaddr_un *)(socketptr->local.sa))->sun_path,
DD_BUFLEN - len);
SOCKET_ADDR_COPY(newsocketptr->remote, socketptr->local.sa, SIZEOF(struct sockaddr_un));
+ newsocketptr->remote.ai.ai_addrlen = socketptr->local.ai.ai_addrlen;
}
# endif
dsocketptr->iod->dollar.key[DD_BUFLEN - 1] = '\0'; /* In case we fill the buffer */
+ newsocketptr->remote.ai.ai_family = SOCKET_REMOTE_ADDR(newsocketptr)->sa_family;
return 0;
}
diff --git a/sr_port/iosocket_write.c b/sr_port/iosocket_write.c
index 02e3944..03c9ba4 100644
--- a/sr_port/iosocket_write.c
+++ b/sr_port/iosocket_write.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -44,6 +44,7 @@ error_def(ERR_CURRSOCKOFR);
error_def(ERR_DELIMSIZNA);
UNIX_ONLY(error_def(ERR_NOPRINCIO);)
error_def(ERR_NOSOCKETINDEV);
+error_def(ERR_SOCKPASSDATAMIX);
error_def(ERR_SOCKWRITE);
error_def(ERR_TEXT);
error_def(ERR_ZFF2MANY);
@@ -101,7 +102,12 @@ void iosocket_write_real(mstr *v, boolean_t convert_output)
dsocketptr = (d_socket_struct *)iod->dev_sp;
if (0 >= dsocketptr->n_socket)
{
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
+# ifndef VMS
+ if (iod == io_std_device.out)
+ ionl_write(v);
+ else
+# endif
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
return;
}
if (dsocketptr->n_socket <= dsocketptr->current_socket)
@@ -112,17 +118,17 @@ void iosocket_write_real(mstr *v, boolean_t convert_output)
if (dsocketptr->mupintr)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO);
socketptr = dsocketptr->socket[dsocketptr->current_socket];
+ ENSURE_DATA_SOCKET(socketptr);
#ifdef MSG_NOSIGNAL
flags = MSG_NOSIGNAL; /* return EPIPE instead of SIGPIPE */
#else
flags = 0;
#endif
+ tempv = *v;
socketptr->lastop = TCP_WRITE;
if (socketptr->first_write)
{ /* First WRITE, do following
- 1. Transition to UTF16BE if ochset is UTF16 and WRITE a BOM
- 2. Convert ZFF into ochset format so we don't need to convert every time ZFF is output
- 3. Convert DELIMITER 0 to OCHSET format to avoid repeated conversions of DELIM0 on output
+ Transition to UTF16BE if ochset is UTF16 and WRITE a BOM
*/
if (CHSET_UTF16 == iod->ochset)
{
@@ -142,38 +148,40 @@ void iosocket_write_real(mstr *v, boolean_t convert_output)
prin_out_dev_failure = FALSE;
#endif
}
- if (CHSET_UTF16BE == iod->ochset || CHSET_UTF16LE == iod->ochset) /* need conversion of ZFF and DELIM0 */
- {
- if (0 < socketptr->zff.len)
- {
- new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset], &socketptr->zff, NULL,
- NULL);
- if (MAX_ZFF_LEN < new_len)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZFF2MANY, 2, new_len, MAX_ZFF_LEN);
- if (NULL != socketptr->zff.addr) /* we rely on newsocket.zff.addr being set to NULL
- in iosocket_create() */
- socketptr->zff.addr = (char *)malloc(MAX_ZFF_LEN);
- socketptr->zff.len = new_len;
- UNICODE_ONLY(socketptr->zff.char_len = 0); /* don't care */
- memcpy(socketptr->zff.addr, stringpool.free, new_len);
- }
+ socketptr->first_write = FALSE;
- if (0 < socketptr->n_delimiter)
+ }
+ if (CHSET_UTF16BE == iod->ochset || CHSET_UTF16LE == iod->ochset)
+ {
+ if ((0 < socketptr->zff.len) && (socketptr->zff.addr == socketptr->ozff.addr))
+ { /* Convert ZFF into ochset format so we don't need to convert every time ZFF is output */
+ new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset], &socketptr->zff, NULL,
+ NULL);
+ if (MAX_ZFF_LEN < new_len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZFF2MANY, 2, new_len, MAX_ZFF_LEN);
+ socketptr->ozff.addr = (char *)malloc(MAX_ZFF_LEN); /* should not need */
+ socketptr->ozff.len = new_len;
+ UNICODE_ONLY(socketptr->ozff.char_len = 0); /* don't care */
+ memcpy(socketptr->ozff.addr, stringpool.free, new_len);
+ if (tempv.addr == socketptr->zff.addr)
+ tempv = socketptr->ozff; /* from iosocket_wtff so use converted form */
+ }
+ if ((0 < socketptr->n_delimiter) && (socketptr->odelimiter0.addr == socketptr->delimiter[0].addr))
+ { /* Convert DELIMITER 0 to OCHSET format to avoid repeated conversions of DELIM0 on output */
+ new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset],
+ &socketptr->delimiter[0], NULL, NULL);
+ if (MAX_DELIM_LEN < new_len)
{
- new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset],
- &socketptr->delimiter[0], NULL, NULL);
- if (MAX_DELIM_LEN < new_len)
- {
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DELIMSIZNA);
- return;
- }
- socketptr->odelimiter0.len = new_len;
- UNICODE_ONLY(socketptr->odelimiter0.char_len = socketptr->delimiter[0].char_len);
- socketptr->odelimiter0.addr = malloc(new_len);
- memcpy(socketptr->odelimiter0.addr, stringpool.free, new_len);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DELIMSIZNA);
+ return;
}
+ socketptr->odelimiter0.len = new_len;
+ UNICODE_ONLY(socketptr->odelimiter0.char_len = socketptr->delimiter[0].char_len);
+ socketptr->odelimiter0.addr = malloc(new_len);
+ memcpy(socketptr->odelimiter0.addr, stringpool.free, new_len);
+ if (tempv.addr == socketptr->delimiter[0].addr)
+ tempv = socketptr->odelimiter0; /* from iosocket_wteol so use converted form */
}
- socketptr->first_write = FALSE;
}
memcpy(iod->dollar.device, "0", SIZEOF("0"));
if (CHSET_M != iod->ochset)
@@ -200,11 +208,9 @@ void iosocket_write_real(mstr *v, boolean_t convert_output)
by whomever needs it without us forcing a garbage collection due to IO reformat.
*/
/* stringpool.free += new_len; */
- } else
- tempv = *v;
+ }
}
- } else
- tempv = *v;
+ }
if (0 != (in_b_len = tempv.len))
{
DBGSOCK2((stdout, "socwrite: starting output loop (%d bytes) - iodwidth: %d wrap: %d\n",
diff --git a/sr_port/iosocket_wteol.c b/sr_port/iosocket_wteol.c
index 2ecba21..5a3253f 100644
--- a/sr_port/iosocket_wteol.c
+++ b/sr_port/iosocket_wteol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,8 +22,13 @@
#include "iottdef.h"
#include "iosocketdef.h"
+#ifndef VMS
+GBLREF io_pair io_std_device;
+#endif
+
error_def(ERR_CURRSOCKOFR);
error_def(ERR_NOSOCKETINDEV);
+error_def(ERR_SOCKPASSDATAMIX);
void iosocket_wteol(int4 val, io_desc *io_ptr)
{
@@ -36,7 +41,12 @@ void iosocket_wteol(int4 val, io_desc *io_ptr)
dsocketptr = (d_socket_struct *)io_ptr->dev_sp;
if (0 >= dsocketptr->n_socket)
{
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
+# ifndef VMS
+ if (io_ptr == io_std_device.out)
+ ionl_wteol(val, io_ptr);
+ else
+# endif
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
return;
}
if (dsocketptr->current_socket >= dsocketptr->n_socket)
@@ -45,6 +55,7 @@ void iosocket_wteol(int4 val, io_desc *io_ptr)
return;
}
socketptr = dsocketptr->socket[dsocketptr->current_socket];
+ ENSURE_DATA_SOCKET(socketptr);
assert(val);
io_ptr->esc_state = START;
if (socketptr->n_delimiter > 0)
diff --git a/sr_port/iosocket_wtff.c b/sr_port/iosocket_wtff.c
index 9c2f558..747f069 100644
--- a/sr_port/iosocket_wtff.c
+++ b/sr_port/iosocket_wtff.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,9 +19,13 @@
#include "iosocketdef.h"
GBLREF io_pair io_curr_device;
+#ifndef VMS
+GBLREF io_pair io_std_device;
+#endif
error_def(ERR_CURRSOCKOFR);
error_def(ERR_NOSOCKETINDEV);
+error_def(ERR_SOCKPASSDATAMIX);
void iosocket_wtff(void)
{
@@ -35,7 +39,12 @@ void iosocket_wtff(void)
dsocketptr = (d_socket_struct *)iod->dev_sp;
if (0 >= dsocketptr->n_socket)
{
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
+# ifndef VMS
+ if (iod == io_std_device.out)
+ ionl_wtff();
+ else
+# endif
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
return;
}
if (dsocketptr->current_socket >= dsocketptr->n_socket)
@@ -44,8 +53,9 @@ void iosocket_wtff(void)
return;
}
socketptr = dsocketptr->socket[dsocketptr->current_socket];
- if (socketptr->zff.len)
- iosocket_write_real(&socketptr->zff, FALSE);
+ ENSURE_DATA_SOCKET(socketptr);
+ if (socketptr->ozff.len)
+ iosocket_write_real(&socketptr->ozff, FALSE);
iosocket_flush(iod);
iod->dollar.x = 0;
iod->dollar.y = 0;
diff --git a/sr_port/iosocketdef.h b/sr_port/iosocketdef.h
index a7405d6..90ec294 100644
--- a/sr_port/iosocketdef.h
+++ b/sr_port/iosocketdef.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -158,7 +158,11 @@ typedef struct
if (NULL != SOCKPTR->buffer) \
free(SOCKPTR->buffer); \
if (NULL != SOCKPTR->zff.addr) \
+ { \
+ if ((NULL != SOCKPTR->ozff.addr) && (SOCKPTR->ozff.addr != SOCKPTR->zff.addr)) \
+ free(SOCKPTR->ozff.addr); \
free(SOCKPTR->zff.addr); \
+ } \
if (NULL != SOCKPTR->local.sa) \
free(SOCKPTR->local.sa); \
if (NULL != SOCKPTR->remote.sa) \
@@ -167,6 +171,8 @@ typedef struct
free(SOCKPTR->local.saddr_ip); \
if (NULL != SOCKPTR->remote.saddr_ip) \
free(SOCKPTR->remote.saddr_ip); \
+ if (NULL != SOCKPTR->parenthandle) \
+ free(SOCKPTR->parenthandle); \
iosocket_delimiter((unsigned char *)NULL, 0, SOCKPTR, TRUE); \
free(SOCKPTR); \
}
@@ -176,29 +182,81 @@ typedef struct
NEWSOCKPTR = (socket_struct *)malloc(SIZEOF(socket_struct)); \
*NEWSOCKPTR = *SOCKPTR; \
if (NULL != SOCKPTR->buffer) \
+ { \
+ NEWSOCKPTR->buffered_length = NEWSOCKPTR->buffered_offset = 0; \
NEWSOCKPTR->buffer = (char *)malloc(SOCKPTR->buffer_size); \
- if (NULL != SOCKPTR->zff.addr) \
+ } \
+ if ((0 != SOCKPTR->zff.len) && (NULL != SOCKPTR->zff.addr)) \
{ \
NEWSOCKPTR->zff.addr = (char *)malloc(MAX_ZFF_LEN); \
memcpy(NEWSOCKPTR->zff.addr, SOCKPTR->zff.addr, SOCKPTR->zff.len); \
+ if ((NULL != SOCKPTR->ozff.addr) && (SOCKPTR->zff.addr != SOCKPTR->ozff.addr)) \
+ { \
+ NEWSOCKPTR->ozff.addr = (char *)malloc(MAX_ZFF_LEN); \
+ memcpy(NEWSOCKPTR->ozff.addr, SOCKPTR->ozff.addr, SOCKPTR->ozff.len); \
+ NEWSOCKPTR->ozff.len = SOCKPTR->ozff.len; \
+ } else \
+ NEWSOCKPTR->ozff = NEWSOCKPTR->zff; \
+ } else \
+ { \
+ NEWSOCKPTR->zff.len = NEWSOCKPTR->ozff.len = 0; \
+ NEWSOCKPTR->zff.addr = NEWSOCKPTR->ozff.addr = NULL; \
} \
if (NULL != SOCKPTR->local.sa) \
{ \
NEWSOCKPTR->local.sa = (struct sockaddr *)malloc(SOCKPTR->local.ai.ai_addrlen); \
memcpy(NEWSOCKPTR->local.sa, SOCKPTR->local.sa, SOCKPTR->local.ai.ai_addrlen); \
+ NEWSOCKPTR->local.ai.ai_addr = NEWSOCKPTR->local.sa; \
} \
if (NULL != SOCKPTR->remote.sa) \
{ \
NEWSOCKPTR->remote.sa = (struct sockaddr *)malloc(SOCKPTR->remote.ai.ai_addrlen); \
memcpy(NEWSOCKPTR->remote.sa, SOCKPTR->remote.sa, SOCKPTR->remote.ai.ai_addrlen); \
+ NEWSOCKPTR->remote.ai.ai_addr = NEWSOCKPTR->remote.sa; \
} \
if (NULL != SOCKPTR->local.saddr_ip) \
STRNDUP(SOCKPTR->local.saddr_ip, SA_MAXLEN, NEWSOCKPTR->local.saddr_ip); \
if (NULL != SOCKPTR->remote.saddr_ip) \
STRNDUP(SOCKPTR->remote.saddr_ip, SA_MAXLEN, NEWSOCKPTR->remote.saddr_ip); \
+ if (NULL != SOCKPTR->parenthandle) \
+ NEWSOCKPTR->parenthandle = NULL; \
iosocket_delimiter_copy(SOCKPTR, NEWSOCKPTR); \
}
+#ifndef VMS
+enum socket_pass_type
+{
+ sockpass_new,
+ sockpass_data,
+ sockpass_sock
+};
+
+#define ENSURE_DATA_SOCKET(SOCKPTR) \
+{ \
+ if (socket_local == (SOCKPTR)->protocol) \
+ { \
+ if (sockpass_new == (SOCKPTR)->passtype) \
+ (SOCKPTR)->passtype = sockpass_data; \
+ else if (sockpass_sock == (SOCKPTR)->passtype) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_SOCKPASSDATAMIX, 0); \
+ } \
+}
+
+#define ENSURE_PASS_SOCKET(SOCKPTR) \
+{ \
+ if (socket_local == (SOCKPTR)->protocol) \
+ { \
+ if (sockpass_new == (SOCKPTR)->passtype) \
+ (SOCKPTR)->passtype = sockpass_sock; \
+ else if (sockpass_data == (SOCKPTR)->passtype) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_SOCKPASSDATAMIX, 0); \
+ } \
+}
+#else
+#define ENSURE_DATA_SOCKET(SOCKPTR)
+#define ENSURE_PASS_SOCKET(SOCKPTR)
+#endif
+
enum socket_state
{
socket_connected,
@@ -208,6 +266,15 @@ enum socket_state
socket_connect_inprogress
};
+enum socket_creator
+{
+ creator_listen,
+ creator_accept,
+ creator_connect,
+ creator_principal,
+ creator_passed
+};
+
enum socket_protocol
{
socket_tcpip,
@@ -266,15 +333,18 @@ typedef struct socket_struct_type
boolean_t first_write;
boolean_t def_moreread_timeout; /* true if deviceparameter morereadtime defined in open or use */
#ifndef VMS
- boolean_t passedfd; /* true if WRITE /ACCEPT or /PASS */
+ enum socket_pass_type passtype; /* prevent mix of data and socket passing on LOCAL sockets */
uint filemode; /* for LOCAL */
uint filemode_mask; /* to tell which modes specified */
uic_struct_int uic;
#endif
mstr zff;
+ mstr ozff; /* UTF-16 if chset is UTF-16 else copy of zff */
uint4 lastaction; /* waitcycle count */
uint4 readycycle; /* when was ready */
boolean_t pendingevent; /* if listening, needs accept */
+ enum socket_creator howcreated;
+ char *parenthandle; /* listening socket this created from */
} socket_struct;
typedef struct socket_interrupt_type
@@ -296,6 +366,8 @@ typedef struct d_socket_struct_type
int4 current_socket; /* current socket index */
int4 n_socket; /* number of sockets */
uint4 waitcycle; /* count waits */
+ boolean_t ichset_specified;
+ boolean_t ochset_specified;
struct io_desc_struct *iod; /* Point back to main IO descriptor block */
struct socket_struct_type *socket[1]; /* Array size determined by gtm_max_sockets */
} d_socket_struct;
diff --git a/sr_port/is_file_identical.h b/sr_port/is_file_identical.h
index 60d4a60..2c61590 100644
--- a/sr_port/is_file_identical.h
+++ b/sr_port/is_file_identical.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,6 +22,6 @@ bool is_gdid_gdid_identical(gd_id_ptr_t fid_1, gd_id_ptr_t fid_2);
bool is_gdid_identical(gd_id_ptr_t fid1, gd_id_ptr_t fid2);
bool is_gdid_stat_identical(gd_id_ptr_t fid, struct stat *stat_buf);
void set_gdid_from_stat(gd_id_ptr_t fid, struct stat *stat_buf);
-boolean_t filename_to_id(gd_id_ptr_t fid, char *filename);
+uint4 filename_to_id(gd_id_ptr_t fid, char *filename);
#endif
#endif
diff --git a/sr_port/jnl.h b/sr_port/jnl.h
index cce76cc..3334020 100644
--- a/sr_port/jnl.h
+++ b/sr_port/jnl.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -37,6 +37,8 @@ error_def(ERR_JNLENDIANLITTLE);
* 1) Update JNL_VER_THIS
* 2) Add REPL_JNL_Vxx enum to repl_jnl_t typedef AND Vxx_JNL_VER #define in repl_filter.h
* 3) Add an entry each to repl_filter_old2cur & repl_filter_cur2old arrays in repl_filter.c.
+ * 4) Bump JNL_EXTR_LABEL and JNL_DET_EXTR_LABEL as appropriate in muprec.h.
+ * This is not needed if for example the newly added jnl record types dont get extracted at all.
* If the FILTER format is also changing, then do the following as well
* 4) Add REPL_FILTER_Vxx enum to repl_filter_t typedef in repl_filter.h
* 5) Add/Edit IF_xTOy macros in repl_filter.h to transform from/to the NEW jnl format version only.
@@ -52,8 +54,8 @@ error_def(ERR_JNLENDIANLITTLE);
* which needs to change to say IF_curTO17 if the earliest supported version changes to V17 or so).
*
*/
-#define JNL_LABEL_TEXT "GDSJNL23" /* see above comment paragraph for todos whenever this is changed */
-#define JNL_VER_THIS 23
+#define JNL_LABEL_TEXT "GDSJNL24" /* see above comment paragraph for todos whenever this is changed */
+#define JNL_VER_THIS 24
#define JNL_VER_EARLIEST_REPL 17 /* Replication filter support starts here GDSJNL17 = GT.M V5.1-000.
* (even though it should be V5.0-000, since that is pre-multisite,
* the replication connection with V55000 will error out at handshake
@@ -69,7 +71,7 @@ error_def(ERR_JNLENDIANLITTLE);
* Actually JRT_HISTREC is a higher record type than JRT_UZTRIG but it is only
* sent through the replication pipe and never seen by filter routines.
*/
-#define ALIGN_KEY 0xdeadbeef
+#define JRT_MAX_V24 JRT_ULGTRIG /* Max jnlrec type in GDSJNL22/GDSJNL23 that can be input to replication filter */
#ifdef UNIX
# define JNL_ALLOC_DEF 2048
@@ -145,14 +147,24 @@ error_def(ERR_JNLENDIANLITTLE);
#ifdef GTM_TRIGGER
/* Define maximum size that $ZTWORMHOLE can be. Since $ZTWORMHOLE should be able to fit in a journal record and the
- * minimum alignsize is 128K, we do not want it to go more than 128K (that way irrespective of whatever alignsize the user
- * specifies for the journal file, $ZTWORMHOLE will fit in the journal record). Leaving a max of 512 bytes for the
- * journal record prefix/suffix (32-byte overhead) and MIN_ALIGN_RECLEN (see comment in JNL_MAX_RECLEN macro for why
- * this is needed) we allow for a max of 128K-512 bytes in $ZTWORMHOLE.
+ * minimum alignsize used to be 128K (until V55000), we did not want it to go more than 128K (that way irrespective
+ * of whatever alignsize the user specifies for the journal file, $ZTWORMHOLE will fit in the journal record). Leaving
+ * a max of 512 bytes for the journal record prefix/suffix (32-byte overhead) and MIN_ALIGN_RECLEN (see comment in
+ * JNL_MAX_RECLEN macro for why this is needed) we had allowed for a max of 128K-512 bytes in $ZTWORMHOLE. The minimum
+ * alignsize (JNL_MIN_ALIGNSIZE) has changed to 2Mb (since V60000) and so we can potentially increase the maximum
+ * $ZTWORMHOLE length to be 1Mb but we defer doing this until there is a need for this bigger length.
*/
#define MAX_ZTWORMHOLE_LEN (128 * 1024)
#define MAX_ZTWORMHOLE_SIZE (MAX_ZTWORMHOLE_LEN - 512)
#define MAX_ZTWORM_JREC_LEN (MAX_ZTWORMHOLE_LEN - MIN_ALIGN_RECLEN)
+
+/* Define maximum size that a LGTRIG jnl record can get to. Cannot exceed minimum align size for sure */
+#define MAX_LGTRIG_LEN ((1 << 20) + (1 << 15)) /* 1Mb for XECUTE string part of the trigger,
+ * 32K for rest of trigger definition. Together this should
+ * still be less than 2Mb which is the JNL_MIN_ALIGNSIZE
+ */
+#define MAX_LGTRIG_JREC_LEN (MAX_LGTRIG_LEN + DISK_BLOCK_SIZE) /* Give 512 more bytes for journal record related
+ * overhead (jrec_prefix etc.) */
#endif
#define MIN_YIELD_LIMIT 0
@@ -283,42 +295,42 @@ error_def(ERR_JNLENDIANLITTLE);
*/
#define JNL_HDR_ENDIAN_OFFSET 8
-#define CHECK_JNL_FILE_IS_USABLE(JFH, STATUS, DO_GTMPUTMSG, JNL_FN_LEN, JNL_FN) \
-{ \
- boolean_t check_failed = FALSE; \
- uint4 lcl_status; \
- \
- assert(JNL_HDR_ENDIAN_OFFSET == OFFSETOF(jnl_file_header, is_little_endian)); \
- if (0 != MEMCMP_LIT((JFH)->label, JNL_LABEL_TEXT)) \
- { \
- lcl_status = ERR_JNLBADLABEL; \
- check_failed = TRUE; \
- } \
- BIGENDIAN_ONLY( \
- else if ((JFH)->is_little_endian) \
- { \
- lcl_status = ERR_JNLENDIANLITTLE; \
- check_failed = TRUE; \
- } \
- ) \
- LITTLEENDIAN_ONLY( \
- else if (!(JFH)->is_little_endian) \
- { \
- lcl_status = ERR_JNLENDIANBIG; \
- check_failed = TRUE; \
- } \
- ) \
- /* Currently, we can do one gtm_putmsg for any of the above 3 error messages \
- * because all of them have a fao count of 2 and expect jnl_fn_len and jnl_fn \
- * as arguments. If a new error gets added and has a different fao format, \
- * then the below gtm_putmsg has to be done differently based on that error. \
- */ \
- if (check_failed) \
- { \
- STATUS = lcl_status; \
- if (DO_GTMPUTMSG) \
- gtm_putmsg(VARLSTCNT(4) lcl_status, 2, JNL_FN_LEN, JNL_FN); \
- } \
+#define CHECK_JNL_FILE_IS_USABLE(JFH, STATUS, DO_GTMPUTMSG, JNL_FN_LEN, JNL_FN) \
+{ \
+ boolean_t check_failed = FALSE; \
+ uint4 lcl_status; \
+ \
+ assert(JNL_HDR_ENDIAN_OFFSET == OFFSETOF(jnl_file_header, is_little_endian)); \
+ if (0 != MEMCMP_LIT((JFH)->label, JNL_LABEL_TEXT)) \
+ { \
+ lcl_status = ERR_JNLBADLABEL; \
+ check_failed = TRUE; \
+ } \
+ BIGENDIAN_ONLY( \
+ else if ((JFH)->is_little_endian) \
+ { \
+ lcl_status = ERR_JNLENDIANLITTLE; \
+ check_failed = TRUE; \
+ } \
+ ) \
+ LITTLEENDIAN_ONLY( \
+ else if (!(JFH)->is_little_endian) \
+ { \
+ lcl_status = ERR_JNLENDIANBIG; \
+ check_failed = TRUE; \
+ } \
+ ) \
+ /* Currently, we can do one gtm_putmsg for any of the above 3 error messages \
+ * because all of them have a fao count of 2 and expect jnl_fn_len and jnl_fn \
+ * as arguments. If a new error gets added and has a different fao format, \
+ * then the below gtm_putmsg has to be done differently based on that error. \
+ */ \
+ if (check_failed) \
+ { \
+ STATUS = lcl_status; \
+ if (DO_GTMPUTMSG) \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) lcl_status, 2, JNL_FN_LEN, JNL_FN); \
+ } \
}
/* Token generation used in non-replicated journaled environment. Note the assumption here
@@ -456,9 +468,9 @@ typedef struct
bytcnt, /* Number of bytes written */
errcnt, /* Number of errors during writing */
reccnt[JRT_RECTYPES]; /* Number of records written per opcode */
- int filler_align[35 - JRT_RECTYPES]; /* So buff below starts on even (QW) keel */
- /* Note the above filler will fail if JRT_RECTYPES grows beyond 31 elements and give compiler warning in VMS
- * if JRT_RECTYPES equals 31. In that case, change the start num to the next odd number above MAX(31,JRT_RECTYPES).
+ int filler_align[37 - JRT_RECTYPES]; /* So buff below starts on even (QW) keel */
+ /* Note the above filler will fail if JRT_RECTYPES grows beyond 37 elements and give compiler warning in VMS
+ * if JRT_RECTYPES equals 37. In that case, change the start num to the next odd number above MAX(37,JRT_RECTYPES).
*/
volatile jnl_tm_t prev_jrec_time; /* to ensure that time never decreases across successive jnl records */
volatile int4 free_update_pid; /* pid that is updating jb->free and jb->freeaddr */
@@ -471,6 +483,8 @@ typedef struct
uint4 max_jrec_len; /* copy of max_jrec_len from journal file header */
uint4 fs_block_size; /* underlying journal file system block size;
* primarily used in Unix, 512 in VMS */
+ volatile uint4 post_epoch_freeaddr; /* virtual on-disk address after last epoch */
+ boolean_t last_eof_written; /* No more records may be written to the file due to autoswitch */
/* CACHELINE_PAD macros provide spacing between the following latches so that they do
not interfere with each other which can happen if they fall in the same data cacheline
of a processor.
@@ -559,6 +573,7 @@ typedef enum
JNL_ZKILL,
# ifdef GTM_TRIGGER
JNL_ZTWORM,
+ JNL_LGTRIG,
JNL_ZTRIG,
# endif
JA_MAX_TYPES
@@ -669,8 +684,9 @@ typedef struct
/* The below two arrays are unused in VMS but defined there to keep the layout similar between Unix & VMS */
seq_num strm_start_seqno[MAX_SUPPL_STRMS];
seq_num strm_end_seqno[MAX_SUPPL_STRMS];
+ boolean_t last_eof_written; /* No more records may be written to the file due to autoswitch */
/* filler remaining */
- char filler[440];
+ char filler[436];
} jnl_file_header;
typedef struct
@@ -737,9 +753,9 @@ typedef struct
*/
#define JS_MAX_MASK (1 << 8) /* max of 8 bits we have for mask */
-/* Note that even though mumps_node, ztworm_str, ztrig_str and align_str are members defined as type "jnl_string" below,
+/* Note that even though mumps_node, ztworm_str, lgtrig_str, align_str are members defined as type "jnl_string" below,
* the "nodeflags" field is initialized to non-zero values ONLY in the case of the mumps_node member.
- * For ztworm_str and align_str, nodeflags is guaranteed to be zero so the 24-bit "length" member
+ * For ztworm_str, lgtrig_str and align_str, nodeflags is guaranteed to be zero so the 24-bit "length" member
* can even be used as a 32-bit length (if necessary) without issues. This is why nodeflags is
* defined in a different order (BEFORE or AFTER the "length" member) based on big-endian or little-endian.
*/
@@ -795,8 +811,8 @@ typedef struct /* variable length */
*/
unsigned short filler_short;
unsigned short num_participants; /* # of regions that wrote a TCOM record in their jnl files.
- * Currently written only for TSET/TKILL/TZTWORM records.
- * Uninitialized for all other types of SET/KILL/ZTWORM records.
+ * Currently written only for TSET/TKILL/TZTWORM/TLGTRIG/TZTRIG records.
+ * Uninitialized for USET/UKILL/UZTWORM/ULGTRIG/UZTRIG records.
*/
jnl_string mumps_node; /* For set/kill/zkill : {jnl_str_len_t key_len, char key[key_len]} */
/* For set additionally : {mstr_len_t data_len, char data[data_len]} */
@@ -815,12 +831,31 @@ typedef struct /* variable length */
*/
unsigned short filler_short;
unsigned short num_participants; /* # of regions that wrote a TCOM record in their jnl files.
- * Currently written only for TSET/TKILL/TZTWORM records.
- * Uninitialized for all other types of SET/KILL/ZTWORM records.
+ * Currently written only for TSET/TKILL/TZTWORM/TLGTRIG/TZTRIG records.
+ * Uninitialized for USET/UKILL/UZTWORM/ULGTRIG/UZTRIG records.
*/
jnl_string ztworm_str; /* jnl_str_len_t ztworm_str_len, char ztworm_str[ztworm_str_len]} */
} struct_jrec_ztworm;
+/* logical trigger jnl record (TLGTRIG or ULGTRIG record) */
+typedef struct /* variable length */
+{
+ jrec_prefix prefix;
+ token_seq_t token_seq; /* must start at 8-byte boundary */
+ seq_num strm_seqno; /* see "struct_jrec_upd" for comment on the purpose of this field */
+ uint4 update_num; /* 'n' where this is the nth journaled update (across all regions) in this TP
+ * transaction. n=1 for the first update inside TP, 2 for the second update
+ * inside TP and so on. Needed so journal recovery and update process can play
+ * all the updates inside of one TP transaction in the exact same order as GT.M.
+ */
+ unsigned short filler_short;
+ unsigned short num_participants; /* # of regions that wrote a TCOM record in their jnl files.
+ * Currently written only for TSET/TKILL/TZTWORM/TLGTRIG/TZTRIG records.
+ * Uninitialized for USET/UKILL/UZTWORM/ULGTRIG/UZTRIG records.
+ */
+ jnl_string lgtrig_str; /* jnl_str_len_t lgtrig_str_len, char lgtrig_str[lgtrig_str_len]} */
+} struct_jrec_lgtrig;
+
#define INVALID_UPDATE_NUM (uint4)-1
typedef struct /* variable length */
@@ -967,6 +1002,7 @@ typedef union
jrec_prefix prefix;
struct_jrec_upd jrec_set_kill; /* JRT_SET or JRT_KILL or JRT_ZTRIG record will use this format */
struct_jrec_ztworm jrec_ztworm;
+ struct_jrec_lgtrig jrec_lgtrig;
struct_jrec_blk jrec_pblk,
jrec_aimg;
struct_jrec_align jrec_align;
@@ -995,6 +1031,7 @@ typedef union
#define TRUNC_RECLEN SIZEOF(struct_jrec_trunc)
/* Macro to access variable size record's fixed part's size */
#define FIXED_ZTWORM_RECLEN OFFSETOF(struct_jrec_ztworm, ztworm_str)
+#define FIXED_LGTRIG_RECLEN OFFSETOF(struct_jrec_lgtrig, lgtrig_str)
#define FIXED_UPD_RECLEN OFFSETOF(struct_jrec_upd, mumps_node)
#define MIN_ALIGN_RECLEN (OFFSETOF(struct_jrec_align, align_str.text[0]) + JREC_SUFFIX_SIZE)
#define FIXED_ALIGN_RECLEN OFFSETOF(struct_jrec_align, align_str.text[0])
@@ -1347,13 +1384,15 @@ typedef struct
/* The below macro now relies on MAX_STRLEN value rather than on CSD->blk_size used previously because
* with nodes spanning blocks journal records might be comprised of several blocks, with the limit of
- * MAX_STRLEN for the actual database record.
+ * MAX_STRLEN for the actual database record. But that only takes care of the value part of the record.
+ * The key can still be MAX_KEY_SZ long. So take that into account as well.
*/
#ifdef UNIX
-# define JNL_MAX_SET_KILL_RECLEN(CSD) (uint4)ROUND_UP2((FIXED_UPD_RECLEN + JREC_SUFFIX_SIZE) + MAX_STRLEN + \
- SIZEOF(jnl_str_len_t) + SIZEOF(mstr_len_t), JNL_REC_START_BNDRY)
+# define JNL_MAX_SET_KILL_RECLEN(CSD) (uint4)ROUND_UP2((FIXED_UPD_RECLEN + JREC_SUFFIX_SIZE) \
+ + MAX_KEY_SZ + MAX_STRLEN \
+ + SIZEOF(jnl_str_len_t) + SIZEOF(mstr_len_t), JNL_REC_START_BNDRY)
#else
-# define JNL_MAX_SET_KILL_RECLEN(CSD) (uint4)ROUND_UP2(FIXED_UPD_RECLEN + JREC_SUFFIX_SIZE \
+# define JNL_MAX_SET_KILL_RECLEN(CSD) (uint4)ROUND_UP2(FIXED_UPD_RECLEN + JREC_SUFFIX_SIZE \
+ ((CSD)->blk_size - SIZEOF(blk_hdr) - SIZEOF(rec_hdr)) \
+ SIZEOF(jnl_str_len_t) + SIZEOF(mstr_len_t), JNL_REC_START_BNDRY) \
/* fixed size part of update record + MAX possible (key + data) len + keylen-len + datalen-len */
@@ -1395,6 +1434,7 @@ typedef struct
\
RC = 0; \
assert(FIXED_UPD_RECLEN == FIXED_ZTWORM_RECLEN); \
+ assert(FIXED_UPD_RECLEN == FIXED_LGTRIG_RECLEN); \
fixed_prefix = FIXED_UPD_RECLEN; \
ASSERT_ENCRYPTION_INITIALIZED; \
span_length = REC_SIZE - fixed_prefix - JREC_SUFFIX_SIZE; \
@@ -1454,6 +1494,7 @@ void jnl_prc_vector(jnl_process_vector *pv);
void jnl_send_oper(jnl_private_control *jpc, uint4 status);
uint4 cre_jnl_file(jnl_create_info *info);
uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_len);
+void cre_jnl_file_intrpt_rename(sgmnt_addrs *csa);
void jfh_from_jnl_info (jnl_create_info *info, jnl_file_header *header);
uint4 jnl_ensure_open(void);
void set_jnl_info(gd_region *reg, jnl_create_info *set_jnl_info);
@@ -1487,9 +1528,10 @@ void mupip_set_journal_fname(jnl_create_info *jnl_info);
uint4 mupip_set_jnlfile_aux(jnl_file_header *header, char *jnl_fname);
void jnl_extr_init(void);
int exttime(uint4 time, char *buffer, int extract_len);
-char *ext2jnlcvt(char *ext_buff, int4 ext_len, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved_strm_seqno);
+unsigned char *ext2jnlcvt(char *ext_buff, int4 ext_len, unsigned char **tr, int *tr_bufsiz,
+ seq_num saved_jnl_seqno, seq_num saved_strm_seqno);
char *ext2jnl(char *ptr, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved_strm_seqno);
-char *jnl2extcvt(jnl_record *rec, int4 jnl_len, char *ext_buff);
+char *jnl2extcvt(jnl_record *rec, int4 jnl_len, char **ext_buff, int *extract_bufsiz);
char *jnl2ext(char *jnl_buff, char *ext_buff);
#endif /* JNL_H_INCLUDED */
diff --git a/sr_port/jnl2ext.c b/sr_port/jnl2ext.c
index 644c14d..6d5ad0c 100644
--- a/sr_port/jnl2ext.c
+++ b/sr_port/jnl2ext.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -54,37 +54,51 @@
CURR = (char *)i2ascl((uchar_ptr_t)CURR, lcl_strm_seqno); \
}
-/*
- * Generic function to convert a journal record into an extract format record.
- * Expects a pointer to the journal record and the length of the buffer and
- * returns the result in ext_buff. If there is a bad format record in between,
- * it returns NULL. It sets jb_stop to the offset of the jnl_buff where
- * the last jnlrecord was processed. On successful conversion, it returns a value
- * ptr, such that ptr - ext_buff would be the length of the extracted buffer.
- * If the ext_len is not enough for the conversion, it returns ext_buff + ext_len
- */
-
+#ifdef DEBUG
GBLREF char *jb_stop;
+#endif
GBLREF char muext_code[][2];
static boolean_t first_tstart = FALSE;
static int4 num_tstarts = 0;
static int4 num_tcommits = 0;
-
-char *jnl2extcvt(jnl_record *rec, int4 jnl_len, char *ext_buff)
+/* Generic function to convert a journal record into an extract format record.
+ * Expects a pointer to the journal record and the length of the buffer and
+ * returns the result in ext_buff. If there is a bad format record in between,
+ * it does an assertpro. It sets jb_stop to the offset of the jnl_buff where
+ * the last jnlrecord was processed. On successful conversion, it returns a value
+ * ptr, such that ptr - ext_buff would be the length of the extracted buffer.
+ */
+char *jnl2extcvt(jnl_record *rec, int4 jnl_len, char **ext_buff, int *extract_bufsiz)
{
- int4 rec_len;
+ int rec_len, tmpbufsiz, tmpsize;
+ char *extbuf, *exttop, *tmp, *origbuf;
+ extbuf = *ext_buff;
+ exttop = extbuf + *extract_bufsiz;
for ( ; jnl_len > JREC_PREFIX_UPTO_LEN_SIZE && jnl_len >= (rec_len = rec->prefix.forwptr) && rec_len > MIN_JNLREC_SIZE; )
{
- ext_buff = jnl2ext((char *)rec, ext_buff);
+ if (MAX_ONE_JREC_EXTRACT_BUFSIZ > (exttop - extbuf))
+ { /* Remaining space not enough to hold the worst-case journal extract of ONE jnl record. Expand linearly */
+ tmpsize = *extract_bufsiz;
+ tmpbufsiz = tmpsize + (JNL2EXTCVT_EXPAND_FACTOR * MAX_ONE_JREC_EXTRACT_BUFSIZ);
+ tmp = malloc(tmpbufsiz);
+ origbuf = *ext_buff;
+ tmpsize = extbuf - origbuf;
+ memcpy(tmp, origbuf, tmpsize);
+ free(origbuf);
+ *ext_buff = tmp;
+ *extract_bufsiz = tmpbufsiz;
+ extbuf = tmp + tmpsize;
+ exttop = tmp + tmpbufsiz;
+ }
+ extbuf = jnl2ext((char *)rec, extbuf);
jnl_len -= rec_len;
rec = (jnl_record *)((char *)rec + rec_len);
}
-
- jb_stop = (char *)rec;
- return ext_buff;
+ DEBUG_ONLY(jb_stop = (char *)rec;)
+ return extbuf;
}
/* This was earlier declared as a local variable, but was moved up, because the HPIA compiler for some reason seems to
@@ -107,19 +121,19 @@ char *jnl2ext(char *jnl_buff, char *ext_buff)
rec_len = rec->prefix.forwptr;
if ((ROUND_DOWN2(rec_len, JNL_REC_START_BNDRY) != rec_len) || rec_len != REC_LEN_FROM_SUFFIX(jnl_buff, rec_len))
{
- assert(FALSE);
+ assertpro(FALSE);
return ext_buff;
}
if (!IS_REPLICATED(rectype))
{
- assert(FALSE);
+ assertpro(FALSE);
return ext_buff;
}
curr = ext_buff;
- /* The following assumes the journal extract format is "GDSJEX06". Whenever that changes (in mur_jnl_ext.c),
- * the below code as well as ext2jnl.c needs to change. Add an assert to let us know of that event.
+ /* The following assumes the journal extract format is "GDSJEX07". Whenever that changes (in mur_jnl_ext.c),
+ * the below code as well as ext2jnl.c will need to change. Add an assert to let us know of that event.
*/
- assert(!MEMCMP_LIT(JNL_EXTR_LABEL,"GDSJEX06"));
+ assert(!MEMCMP_LIT(JNL_EXTR_LABEL,"GDSJEX07"));
if (IS_TUPD(rectype))
{
if (FALSE == first_tstart)
@@ -180,6 +194,8 @@ char *jnl2ext(char *jnl_buff, char *ext_buff)
GET_SHORTP(curr, &muext_code[MUEXT_ZKILL][0]);
else if (IS_ZTWORM(rectype))
GET_SHORTP(curr, &muext_code[MUEXT_ZTWORM][0]);
+ else if (IS_LGTRIG(rectype))
+ GET_SHORTP(curr, &muext_code[MUEXT_LGTRIG][0]);
else if (IS_ZTRIG(rectype))
GET_SHORTP(curr, &muext_code[MUEXT_ZTRIG][0]);
else /* if (JRT_NULL == rectype) */
@@ -205,12 +221,14 @@ char *jnl2ext(char *jnl_buff, char *ext_buff)
}
DELIMIT_CURR;
/* print "update_num" */
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype));
assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
+ assert(&rec->jrec_set_kill.update_num == &rec->jrec_lgtrig.update_num);
curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_set_kill.update_num);
DELIMIT_CURR;
- if (IS_ZTWORM(rectype))
+ if (IS_ZTWORM(rectype) || IS_LGTRIG(rectype))
{
+ assert(&rec->jrec_ztworm.ztworm_str == &rec->jrec_lgtrig.lgtrig_str);
ztwormstr = &rec->jrec_ztworm.ztworm_str;
val_len = ztwormstr->length;
val_ptr = &ztwormstr->text[0];
@@ -230,7 +248,7 @@ char *jnl2ext(char *jnl_buff, char *ext_buff)
key->end = keystr->length;
if (key->end > key->top)
{
- assert(FALSE);
+ assertpro(FALSE);
return ext_buff;
}
memcpy(key->base, &keystr->text[0], keystr->length);
diff --git a/sr_port/jnl_file_close.c b/sr_port/jnl_file_close.c
index 46cb49f..5629020 100644
--- a/sr_port/jnl_file_close.c
+++ b/sr_port/jnl_file_close.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,6 +11,8 @@
#include "mdef.h"
+#include <stddef.h> /* for offsetof, needed for JNL_FILE_TAIL_PRESERVE */
+
#include "gtm_time.h"
#include "gtm_string.h"
@@ -49,6 +51,7 @@
#include "send_msg.h"
#include "eintr_wrappers.h"
#include "anticipatory_freeze.h"
+#include "error.h"
#ifdef UNIX
#include "wcs_clean_dbsync.h"
@@ -59,7 +62,8 @@ GBLREF short astq_dyn_avail;
static const unsigned short zero_fid[3];
#endif
-GBLREF jnl_gbls_t jgbl;
+GBLREF jnl_gbls_t jgbl;
+GBLREF boolean_t in_jnl_file_autoswitch;
error_def(ERR_JNLCLOSE);
error_def(ERR_JNLFLUSH);
@@ -81,6 +85,7 @@ void jnl_file_close(gd_region *reg, bool clean, bool dummy)
uint4 status, read_write_size;
int rc, save_errno, idx;
uint4 jnl_fs_block_size;
+ boolean_t was_in_jnl_file_autoswitch, was_last_eof_written, in_tail;
csa = &FILE_INFO(reg)->s_addrs;
csd = csa->hdr;
@@ -109,8 +114,51 @@ void jnl_file_close(gd_region *reg, bool clean, bool dummy)
header = (jnl_file_header *)(ROUND_UP2((uintszofptr_t)hdr_base, jnl_fs_block_size));
if (clean)
{
- if(!jgbl.mur_extract)
+ was_last_eof_written = jb->last_eof_written;
+ if (!jgbl.mur_extract && !was_last_eof_written)
+ {
+ was_in_jnl_file_autoswitch = in_jnl_file_autoswitch;
+ /* We don't want to switch while closing, so set in_jnl_file_autoswitch,
+ * which allows writing to the tail.
+ */
+ in_jnl_file_autoswitch = TRUE;
+ if (!was_in_jnl_file_autoswitch)
+ {
+ assert(!jgbl.save_dont_reset_gbl_jrec_time);
+ /* Make sure the condition handler can restore the correct value */
+ jgbl.save_dont_reset_gbl_jrec_time = jgbl.dont_reset_gbl_jrec_time;
+ ESTABLISH(jnl_file_autoswitch_ch);
+ }
+ /* Otherwise the caller which set was_in_jnl_file_autoswitch also should have
+ * established the condition handler already.
+ */
+ /* It is possible we still have not written a PINI record in this journal file
+ * (e.g. mupip extend saw the need to do jnl_file_extend inside jnl_write while
+ * trying to write a PINI record). Write a PINI record in that case before closing
+ * the journal file that way the EOF record will have a non-zero pini_addr.
+ * However, if we are already in the tail due to a prior disruption, skip the
+ * pini/pfin and just write the eof.
+ */
+ DEBUG_ONLY(jpc->status = SS_NORMAL);
+ in_tail = (jb->freeaddr > jb->filesize - JNL_FILE_TAIL_PRESERVE);
+ if ((0 == jpc->pini_addr) && !in_tail)
+ {
+ jnl_put_jrt_pini(csa);
+ jnl_put_jrt_pfin(csa);
+ }
jnl_write_eof_rec(csa, &eof_record);
+ if (!was_in_jnl_file_autoswitch)
+ {
+ jgbl.dont_reset_gbl_jrec_time = jgbl.save_dont_reset_gbl_jrec_time;
+ jgbl.save_dont_reset_gbl_jrec_time = FALSE;
+ REVERT;
+ } else
+ /* We were called in autoswitch, so prevent further records from being
+ * written to this file by marking it as last_eof_written.
+ */
+ jb->last_eof_written = TRUE;
+ in_jnl_file_autoswitch = was_in_jnl_file_autoswitch;
+ }
if (SS_NORMAL != (jpc->status = jnl_flush(reg)))
{
send_msg_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_JNLFLUSH, 2, JNL_LEN_STR(csd),
@@ -130,8 +178,9 @@ void jnl_file_close(gd_region *reg, bool clean, bool dummy)
DO_FILE_READ(jpc->channel, 0, header, read_write_size, jpc->status, jpc->status2);
if (SYSCALL_SUCCESS(jpc->status))
{
- if(!jgbl.mur_extract)
+ if (!jgbl.mur_extract && !was_last_eof_written)
{
+ /* If was_last_eof_written is TRUE, we didn't write an eof, so nothing to update. */
assert(header->end_of_data <= eof_addr);
header->end_of_data = eof_addr;
header->eov_timestamp = eof_record.prefix.time;
@@ -148,6 +197,7 @@ void jnl_file_close(gd_region *reg, bool clean, bool dummy)
MUR_ADJUST_STRM_REG_SEQNO_IF_NEEDED(csd, header->strm_end_seqno);
}
# endif
+ header->last_eof_written = jb->last_eof_written;
header->crash = FALSE;
JNL_DO_FILE_WRITE(csa, csd->jnl_file_name, jpc->channel,
0, header, read_write_size, jpc->status, jpc->status2);
diff --git a/sr_port/jnl_file_lost.c b/sr_port/jnl_file_lost.c
index 41d348b..0ef3270 100644
--- a/sr_port/jnl_file_lost.c
+++ b/sr_port/jnl_file_lost.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -68,7 +68,7 @@ uint4 jnl_file_lost(jnl_private_control *jpc, uint4 jnl_stat)
csa = &FILE_INFO(jpc->region)->s_addrs;
break;
default:
- GTMASSERT;
+ assertpro(FALSE && jpc->region->dyn.addr->acc_meth);
}
# ifdef VMS
/* The following assert has been removed as it could be FALSE if the caller is "jnl_file_extend"
@@ -78,14 +78,11 @@ uint4 jnl_file_lost(jnl_private_control *jpc, uint4 jnl_stat)
assert(csa->now_crit);
/* We issue an rts_error (instead of shutting off journaling) in the following cases : {BYPASSOK}
* 1) $gtm_error_on_jnl_file_lost is set to issue runtime error (if not already issued) in case of journaling issues.
- * 2) The process has $gtm_custom_errors set (indicative of anticipatory freeze setup) in which case the goal is to
- * never shut-off journaling
- * 3) If $gtm_custom_errors is not set for this process, but the source server was started with $gtm_custom_errors
- * set. This way, as long as the environment is configured for $gtm_custom_errors individual processes never turn
- * off journaling.
+ * 2) The process has the given message set in $gtm_custom_errors (indicative of instance freeze on error setup)
+ * in which case the goal is to never shut-off journaling
*/
- UNIX_ONLY(instfreeze_environ = (ANTICIPATORY_FREEZE_AVAILABLE
- || ((NULL != jnlpool_ctl) && jnlpool_ctl->instfreeze_environ_inited)));
+ UNIX_ONLY(assert(jnlpool.jnlpool_ctl == jnlpool_ctl));
+ UNIX_ONLY(instfreeze_environ = INST_FREEZE_ON_MSG_ENABLED(csa, jnl_stat));
VMS_ONLY(instfreeze_environ = FALSE);
if ((JNL_FILE_LOST_ERRORS == TREF(error_on_jnl_file_lost)) || instfreeze_environ)
{
@@ -132,8 +129,7 @@ uint4 jnl_file_lost(jnl_private_control *jpc, uint4 jnl_stat)
{
if (SS$_NORMAL == status)
status = gtm_deq(csa->jnl->jnllsb->lockid, NULL, PSL$C_USER, 0);
- if (SS$_NORMAL != status)
- GTMASSERT;
+ assertpro(SS$_NORMAL == status);
}
# else
jnl_file_close(jpc->region, FALSE, FALSE);
diff --git a/sr_port/jnl_file_open_common.c b/sr_port/jnl_file_open_common.c
index 9ff0a4d..2dbcae2 100644
--- a/sr_port/jnl_file_open_common.c
+++ b/sr_port/jnl_file_open_common.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -205,7 +205,9 @@ uint4 jnl_file_open_common(gd_region *reg, off_jnl_t os_file_size)
assert((sm_uc_ptr_t)&jb->buff[jb->buff_off + jb->size] < ((sm_uc_ptr_t)csa->nl + NODE_LOCAL_SPACE(csd)
+ JNL_SHARE_SIZE(csd)));
assert((sm_uc_ptr_t)jb == ((sm_uc_ptr_t)csa->nl + NODE_LOCAL_SPACE(csd) + JNL_NAME_EXP_SIZE));
+ jb->last_eof_written = header->last_eof_written;
jb->freeaddr = jb->dskaddr = UNIX_ONLY(jb->fsync_dskaddr = ) header->end_of_data;
+ jb->post_epoch_freeaddr = jb->freeaddr;
jb->fs_block_size = jnl_fs_block_size;
/* The following is to make sure that the data in jnl_buffer is aligned with the data in the
* disk file on an jnl_fs_block_size boundary. Since we assert that jb->size is a multiple of jnl_fs_block_size,
diff --git a/sr_port/jnl_file_open_switch.c b/sr_port/jnl_file_open_switch.c
index 682f85c..f3d644d 100644
--- a/sr_port/jnl_file_open_switch.c
+++ b/sr_port/jnl_file_open_switch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -55,7 +55,7 @@ uint4 jnl_file_open_switch(gd_region *reg, uint4 sts)
set_jnl_info(reg, &create);
create.no_prev_link = TRUE;
create.no_rename = FALSE;
- assert(!jgbl.forw_phase_recovery || WBTEST_ENABLED(WBTEST_RECOVER_ENOSPC));
+ assert(!jgbl.forw_phase_recovery || WBTEST_ENABLED(WBTEST_RECOVER_ENOSPC) || WBTEST_ENABLED(WBTEST_JNL_CREATE_FAIL));
if (!jgbl.dont_reset_gbl_jrec_time)
SET_GBL_JREC_TIME; /* needed for cre_jnl_file() */
/* else mur_output_record() would have already set jgbl.gbl_jrec_time */
diff --git a/sr_port/jnl_format.c b/sr_port/jnl_format.c
index cdbed5b..8b82198 100644
--- a/sr_port/jnl_format.c
+++ b/sr_port/jnl_format.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -86,6 +86,7 @@ static const enum jnl_record_type jnl_opcode[][5] =
{ JRT_ZKILL, JRT_FZKILL, JRT_TZKILL, JRT_GZKILL, JRT_UZKILL }, /* ZKILL record types */
# ifdef GTM_TRIGGER
{ JRT_BAD, JRT_BAD, JRT_TZTWORM, JRT_BAD, JRT_UZTWORM }, /* ZTWORM record types */
+ { JRT_BAD, JRT_BAD, JRT_TLGTRIG, JRT_BAD, JRT_ULGTRIG }, /* LGTRIG record types */
{ JRT_BAD, JRT_BAD, JRT_TZTRIG, JRT_BAD, JRT_UZTRIG }, /* ZTRIG record types */
# endif
};
@@ -214,6 +215,7 @@ jnl_format_buffer *jnl_format(jnl_action_code opcode, gv_key *key, mval *val, ui
++subcode; /* TP */
tmp_jrec_size = FIXED_UPD_RECLEN + JREC_SUFFIX_SIZE;
assert(FIXED_UPD_RECLEN == FIXED_ZTWORM_RECLEN);
+ assert(FIXED_UPD_RECLEN == FIXED_LGTRIG_RECLEN);
if (!jgbl.forw_phase_recovery)
jgbl.tp_ztp_jnl_upd_num++;
/* In case of forward phase of journal recovery, this would have already been set to appropriate value.
@@ -228,16 +230,16 @@ jnl_format_buffer *jnl_format(jnl_action_code opcode, gv_key *key, mval *val, ui
assert(JA_MAX_TYPES > opcode);
rectype = jnl_opcode[opcode][subcode];
assert(IS_VALID_JRECTYPE(rectype));
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype));
- GTMTRIG_ONLY(assert((JNL_ZTWORM != opcode) || (NULL == key));)
- GTMTRIG_ONLY(assert((JNL_ZTWORM == opcode) || (NULL != key));)
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype));
+ GTMTRIG_ONLY(assert(((JNL_ZTWORM != opcode) && (JNL_LGTRIG != opcode)) || (NULL == key));)
+ GTMTRIG_ONLY(assert((JNL_ZTWORM == opcode) || (JNL_LGTRIG == opcode) || (NULL != key));)
/* Compute actual record length */
if (NULL != key)
{
keystrlen = key->end;
tmp_jrec_size += keystrlen + SIZEOF(jnl_str_len_t);
}
- GTMTRIG_ONLY(assert((JNL_ZTWORM != opcode) || (NULL != val));)
+ GTMTRIG_ONLY(assert(((JNL_ZTWORM != opcode) && (JNL_LGTRIG != opcode)) || (NULL != val));)
assert((JNL_SET != opcode) || (NULL != val));
if (NULL != val)
{
@@ -269,8 +271,11 @@ jnl_format_buffer *jnl_format(jnl_action_code opcode, gv_key *key, mval *val, ui
rec->prefix.jrec_type = rectype;
assert(!IS_SET_KILL_ZKILL_ZTRIG(rectype) || (JNL_MAX_SET_KILL_RECLEN(csd) >= jrec_size));
GTMTRIG_ONLY(assert(!IS_ZTWORM(rectype) || (MAX_ZTWORM_JREC_LEN >= jrec_size));)
+ GTMTRIG_ONLY(assert(MAX_LGTRIG_JREC_LEN <= (JNL_MIN_ALIGNSIZE * DISK_BLOCK_SIZE));)
+ GTMTRIG_ONLY(assert(!IS_LGTRIG(rectype) || (MAX_LGTRIG_JREC_LEN >= jrec_size));)
rec->prefix.forwptr = jrec_size;
assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
+ assert(&rec->jrec_set_kill.update_num == &rec->jrec_lgtrig.update_num);
rec->jrec_set_kill.update_num = jgbl.tp_ztp_jnl_upd_num;
rec->jrec_set_kill.num_participants = 0;
local_buffer = (char *)rec + FIXED_UPD_RECLEN;
diff --git a/sr_port/jnl_rec_table.h b/sr_port/jnl_rec_table.h
index d544dd1..4211309 100644
--- a/sr_port/jnl_rec_table.h
+++ b/sr_port/jnl_rec_table.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,41 +16,46 @@
/*
JNL_TABLE_ENTRY (rectype, extract_rtn, label, update, fixed_size, is_replicated)
*/
-JNL_TABLE_ENTRY (JRT_BAD, NULL, "*BAD* ", NA, FALSE, FALSE) /* 0: Catch-all for invalid record types (must be first) */
+JNL_TABLE_ENTRY (JRT_BAD, NULL, "*BAD* ", NA, FALSE, FALSE) /* 0: Catch-all for invalid record types (must be first) BYPASSOK (line length) */
JNL_TABLE_ENTRY (JRT_PINI, mur_extract_pini, "PINI ", NA, TRUE, FALSE) /* 1: Process initialization */
JNL_TABLE_ENTRY (JRT_PFIN, mur_extract_pfin, "PFIN ", NA, TRUE, FALSE) /* 2: Process termination */
JNL_TABLE_ENTRY (JRT_ZTCOM, mur_extract_tcom, "ZTCOM ", ZTCOMREC, TRUE, FALSE) /* 3: End of "fenced" transaction */
-JNL_TABLE_ENTRY (JRT_KILL, mur_extract_set, "KILL ", KILLREC, FALSE, TRUE) /* 4: After-image logical journal transaction */
-JNL_TABLE_ENTRY (JRT_FKILL, mur_extract_set, "FKILL ", KILLREC|FUPDREC, FALSE, FALSE) /* 5: Like KILL, but the first in a "fenced" transaction */
+JNL_TABLE_ENTRY (JRT_KILL, mur_extract_set, "KILL ", KILLREC, FALSE, TRUE) /* 4: After-image logical journal transaction BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_FKILL, mur_extract_set, "FKILL ", KILLREC|FUPDREC, FALSE, FALSE) /* 5: Like KILL, but the first in a "fenced" transaction BYPASSOK (line length) */
JNL_TABLE_ENTRY (JRT_GKILL, mur_extract_set, "GKILL ", KILLREC|GUPDREC, FALSE, FALSE) /* 6: Like FKILL, but not the first */
-JNL_TABLE_ENTRY (JRT_SET, mur_extract_set, "SET ", SETREC, FALSE, TRUE) /* 7: After-image logical journal transaction */
-JNL_TABLE_ENTRY (JRT_FSET, mur_extract_set, "FSET ", SETREC|FUPDREC, FALSE, FALSE) /* 8: Like SET, but the first in a "fenced" transaction */
+JNL_TABLE_ENTRY (JRT_SET, mur_extract_set, "SET ", SETREC, FALSE, TRUE) /* 7: After-image logical journal transaction BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_FSET, mur_extract_set, "FSET ", SETREC|FUPDREC, FALSE, FALSE) /* 8: Like SET, but the first in a "fenced" transaction BYPASSOK (line length) */
JNL_TABLE_ENTRY (JRT_GSET, mur_extract_set, "GSET ", SETREC|GUPDREC, FALSE, FALSE) /* 9: Like FSET, but not the first */
-JNL_TABLE_ENTRY (JRT_PBLK, mur_extract_blk, "PBLK ", NA, FALSE, FALSE) /* 10: Before-image physical journal transaction */
+JNL_TABLE_ENTRY (JRT_PBLK, mur_extract_blk, "PBLK ", NA, FALSE, FALSE) /* 10: Before-image physical journal transaction BYPASSOK (line length) */
JNL_TABLE_ENTRY (JRT_EPOCH, mur_extract_epoch, "EPOCH ", NA, TRUE, FALSE) /* 11: A "new epoch" */
JNL_TABLE_ENTRY (JRT_EOF, mur_extract_eof, "EOF ", NA, TRUE, FALSE) /* 12: End of file */
-JNL_TABLE_ENTRY (JRT_TKILL, mur_extract_set, "TKILL ", KILLREC|TUPDREC, FALSE, TRUE) /* 13: Like KILL, but the first in a TP transaction */
-JNL_TABLE_ENTRY (JRT_UKILL, mur_extract_set, "UKILL ", KILLREC|UUPDREC, FALSE, TRUE) /* 14: Like TKILL, but not the first */
-JNL_TABLE_ENTRY (JRT_TSET, mur_extract_set, "TSET ", SETREC|TUPDREC, FALSE, TRUE) /* 15: Like SET, but the first in a TP transaction */
+JNL_TABLE_ENTRY (JRT_TKILL, mur_extract_set, "TKILL ", KILLREC|TUPDREC, FALSE, TRUE) /* 13: Like KILL, but the first in a TP transaction BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_UKILL, mur_extract_set, "UKILL ", KILLREC|UUPDREC, FALSE, TRUE) /* 14: Like TKILL, but not the first BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_TSET, mur_extract_set, "TSET ", SETREC|TUPDREC, FALSE, TRUE) /* 15: Like SET, but the first in a TP transaction BYPASSOK (line length) */
JNL_TABLE_ENTRY (JRT_USET, mur_extract_set, "USET ", SETREC|UUPDREC, FALSE, TRUE) /* 16: Like TSET, but not the first */
JNL_TABLE_ENTRY (JRT_TCOM, mur_extract_tcom, "TCOM ", TCOMREC, TRUE, TRUE) /* 17: End of TP transaction */
JNL_TABLE_ENTRY (JRT_ALIGN, mur_extract_align, "ALIGN ", NA, FALSE, FALSE) /* 18: Align record */
JNL_TABLE_ENTRY (JRT_NULL, mur_extract_null, "NULL ", NA, TRUE, TRUE) /* 19: Null record */
-JNL_TABLE_ENTRY (JRT_ZKILL, mur_extract_set, "ZKILL ", ZKILLREC, FALSE, TRUE) /* 20: After-image logical journal transaction */
-JNL_TABLE_ENTRY (JRT_FZKILL, mur_extract_set, "FZKILL ", ZKILLREC|FUPDREC, FALSE, FALSE) /* 21: Like ZKILL, but the first in a "fenced" transaction */
-JNL_TABLE_ENTRY (JRT_GZKILL, mur_extract_set, "GZKILL ", ZKILLREC|GUPDREC, FALSE, FALSE) /* 22: Like FZKILL, but not the first */
-JNL_TABLE_ENTRY (JRT_TZKILL, mur_extract_set, "TZKILL ", ZKILLREC|TUPDREC, FALSE, TRUE) /* 23: Like ZKILL, but the first in a TP transaction */
-JNL_TABLE_ENTRY (JRT_UZKILL, mur_extract_set, "UZKILL ", ZKILLREC|UUPDREC, FALSE, TRUE) /* 24: Like TZKILL, but not the first */
-JNL_TABLE_ENTRY (JRT_INCTN, mur_extract_inctn, "INCTN ", NA, TRUE, FALSE) /* 25: Increment curr_tn only, no logical update */
-JNL_TABLE_ENTRY (JRT_AIMG, mur_extract_blk, "AIMG ", NA, FALSE, FALSE) /* 26: After-image physical journal transaction */
-JNL_TABLE_ENTRY (JRT_TRIPLE, NULL, "TRIPLE ", NA, TRUE, TRUE) /* 27: A REPL_OLD_TRIPLE message minus the 8-byte message
- * header ("type" and "len"). Only used in the
- * replication pipe. Never part of a journal file. */
-JNL_TABLE_ENTRY (JRT_TZTWORM, mur_extract_set, "TZTWORM", ZTWORMREC|TUPDREC, FALSE, TRUE) /* 28: If $ZTWORMHOLE is first record in TP */
-JNL_TABLE_ENTRY (JRT_UZTWORM, mur_extract_set, "UZTWORM", ZTWORMREC|UUPDREC, FALSE, TRUE) /* 29: Like TZTWORM but not the first record in TP */
-JNL_TABLE_ENTRY (JRT_TZTRIG, mur_extract_set, "TZTRIG ", ZTRIGREC|TUPDREC, FALSE, TRUE) /* 30: If ZTRIGGER is first record in TP */
-JNL_TABLE_ENTRY (JRT_UZTRIG, mur_extract_set, "UZTRIG ", ZTRIGREC|UUPDREC, FALSE, TRUE) /* 31: Like TZTRIG but not the first record in TP */
-JNL_TABLE_ENTRY (JRT_HISTREC, NULL, "HISTREC", NA, TRUE, TRUE) /* 32: A REPL_HISTREC message minus the 8-byte message
- * header ("type" and "len"). Only used in the
- * replication pipe. Never part of a journal file. */
-JNL_TABLE_ENTRY (JRT_TRUNC, mur_extract_trunc, "TRUNC ", NA, TRUE, FALSE) /* 33: Record DB file truncate details */
+JNL_TABLE_ENTRY (JRT_ZKILL, mur_extract_set, "ZKILL ", ZKILLREC, FALSE, TRUE) /* 20: After-image logical journal transaction BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_FZKILL, mur_extract_set, "FZKILL ", ZKILLREC|FUPDREC, FALSE, FALSE) /* 21: Like ZKILL, but the first in a "fenced" transaction BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_GZKILL, mur_extract_set, "GZKILL ", ZKILLREC|GUPDREC, FALSE, FALSE) /* 22: Like FZKILL, but not the first BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_TZKILL, mur_extract_set, "TZKILL ", ZKILLREC|TUPDREC, FALSE, TRUE) /* 23: Like ZKILL, but the first in a TP transaction BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_UZKILL, mur_extract_set, "UZKILL ", ZKILLREC|UUPDREC, FALSE, TRUE) /* 24: Like TZKILL, but not the first BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_INCTN, mur_extract_inctn, "INCTN ", NA, TRUE, FALSE) /* 25: Increment curr_tn only, no logical update BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_AIMG, mur_extract_blk, "AIMG ", NA, FALSE, FALSE) /* 26: After-image physical journal transaction BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_TRIPLE, NULL, "TRIPLE ", NA, TRUE, TRUE) /* 27: A REPL_OLD_TRIPLE message minus the 8-byte message BYPASSOK (line length)
+ * header ("type" and "len"). Only used in the BYPASSOK (line length)
+ * replication pipe. Never part of a journal file. BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_TZTWORM, mur_extract_set, "TZTWORM", ZTWORMREC|TUPDREC, FALSE, TRUE) /* 28: If $ZTWORMHOLE is first record in TP BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_UZTWORM, mur_extract_set, "UZTWORM", ZTWORMREC|UUPDREC, FALSE, TRUE) /* 29: Like TZTWORM but not the first record in TP BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_TZTRIG, mur_extract_set, "TZTRIG ", ZTRIGREC|TUPDREC, FALSE, TRUE) /* 30: If ZTRIGGER is first record in TP BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_UZTRIG, mur_extract_set, "UZTRIG ", ZTRIGREC|UUPDREC, FALSE, TRUE) /* 31: Like TZTRIG but not the first record in TP BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_HISTREC, NULL, "HISTREC", NA, TRUE, TRUE) /* 32: A REPL_HISTREC message minus the 8-byte message BYPASSOK (line length)
+ * header ("type" and "len"). Only used in the BYPASSOK (line length)
+ * replication pipe. Never part of a journal file. BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_TRUNC, mur_extract_trunc, "TRUNC ", NA, TRUE, FALSE) /* 33: Record DB file truncate details BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_TLGTRIG, mur_extract_set, "TLGTRIG", LGTRIGREC|TUPDREC, FALSE, TRUE ) /* 34: A LoGical TRIGger record generated by a BYPASSOK (line length)
+ * $ZTRIGGER or MUPIP TRIGGER action and is the BYPASSOK (line length)
+ * first update in this region in a TP transaction BYPASSOK (line length) */
+JNL_TABLE_ENTRY (JRT_ULGTRIG, mur_extract_set, "ULGTRIG", LGTRIGREC|UUPDREC, FALSE, TRUE ) /* 35: Just like TLGTRIG but is NOT the BYPASSOK (line length)
+ * first update in this region in a TP transaction BYPASSOK (line length) */
diff --git a/sr_port/jnl_typedef.h b/sr_port/jnl_typedef.h
index 959de79..3c7da35 100644
--- a/sr_port/jnl_typedef.h
+++ b/sr_port/jnl_typedef.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2011 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,26 +12,29 @@
#ifndef JNL_TYPEDEF_H_INCLUDED
#define JNL_TYPEDEF_H_INCLUDED
+#define TUPDREC 0x00000001
+#define UUPDREC 0x00000002
+#define TCOMREC 0x00000004
+#define TPREC_MASK (TUPDREC | UUPDREC | TCOMREC)
+
+#define FUPDREC 0x00000010
+#define GUPDREC 0x00000020
+#define ZTCOMREC 0x00000040
+#define ZTPREC_MASK (FUPDREC | GUPDREC | ZTCOMREC)
+
#define NA 0
-#define SETREC 0x00000001
-#define KILLREC 0x00000002
-#define ZKILLREC 0x00000004
-#define ZTWORMREC 0x00000008
-#define ZTRIGREC 0x00000800
+#define SETREC 0x00000100
+#define KILLREC 0x00000200
+#define ZKILLREC 0x00000400
+#define ZTWORMREC 0x00000800
+#define ZTRIGREC 0x00001000
+#define LGTRIGREC 0x00002000
#define SET_KILL_ZKILL_MASK (SETREC | KILLREC | ZKILLREC)
#define SET_KILL_ZKILL_ZTWORM_MASK (SETREC | KILLREC | ZKILLREC | ZTWORMREC)
+#define SET_KILL_ZKILL_ZTWORM_LGTRIG_MASK (SETREC | KILLREC | ZKILLREC | ZTWORMREC | LGTRIGREC)
#define SET_KILL_ZKILL_ZTWORM_ZTRIG_MASK (SETREC | KILLREC | ZKILLREC | ZTWORMREC | ZTRIGREC)
-
-#define TUPDREC 0x00000010
-#define UUPDREC 0x00000020
-#define TCOMREC 0x00000040
-#define TPREC_MASK (TUPDREC | UUPDREC | TCOMREC)
-
-#define FUPDREC 0x00000100
-#define GUPDREC 0x00000200
-#define ZTCOMREC 0x00000400
-#define ZTPREC_MASK (FUPDREC | GUPDREC | ZTCOMREC)
+#define SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG_MASK (SETREC | KILLREC | ZKILLREC | ZTWORMREC | LGTRIGREC | ZTRIGREC)
#define FENCE_MASK (TPREC_MASK | ZTPREC_MASK)
@@ -40,38 +43,42 @@ LITREF int jrt_update[JRT_RECTYPES];
LITREF boolean_t jrt_fixed_size[JRT_RECTYPES];
LITREF boolean_t jrt_is_replicated[JRT_RECTYPES];
-#define IS_VALID_RECTYPES_RANGE(rectype) ((JRT_BAD < rectype) && (JRT_RECTYPES > rectype))
-#define IS_REPLICATED(rectype) (jrt_is_replicated[rectype])
-#define IS_FIXED_SIZE(rectype) (jrt_fixed_size[rectype])
-#define IS_SET(rectype) (jrt_update[rectype] & SETREC)
-#define IS_KILL(rectype) (jrt_update[rectype] & KILLREC)
-#define IS_ZKILL(rectype) (jrt_update[rectype] & ZKILLREC)
-#define IS_ZTWORM(rectype) (jrt_update[rectype] & ZTWORMREC)
-#define IS_ZTRIG(rectype) (jrt_update[rectype] & ZTRIGREC)
-#define IS_KILL_ZKILL(rectype) (jrt_update[rectype] & (KILLREC | ZKILLREC))
-#define IS_KILL_ZKILL_ZTRIG(rectype) (jrt_update[rectype] & (KILLREC | ZKILLREC | ZTRIGREC))
-#define IS_SET_KILL_ZKILL_ZTRIG(rectype) (jrt_update[rectype] & (SET_KILL_ZKILL_MASK | ZTRIGREC))
-#define IS_SET_KILL_ZKILL_ZTWORM(rectype) (jrt_update[rectype] & SET_KILL_ZKILL_ZTWORM_MASK)
-#define IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype) (jrt_update[rectype] & SET_KILL_ZKILL_ZTWORM_ZTRIG_MASK)
-#define IS_FENCED(rectype) (jrt_update[rectype] & FENCE_MASK)
-#define IS_TP(rectype) (jrt_update[rectype] & TPREC_MASK)
-#define IS_ZTP(rectype) (jrt_update[rectype] & ZTPREC_MASK)
-#define IS_COM(rectype) (jrt_update[rectype] & (TCOMREC | ZTCOMREC))
-#define IS_FUPD(rectype) (jrt_update[rectype] & FUPDREC)
-#define IS_GUPD(rectype) (jrt_update[rectype] & GUPDREC)
-#define IS_TUPD(rectype) (jrt_update[rectype] & TUPDREC)
-#define IS_UUPD(rectype) (jrt_update[rectype] & UUPDREC)
-#define IS_FUPD_TUPD(rectype) (jrt_update[rectype] & (FUPDREC | TUPDREC))
-#define IS_GUPD_UUPD(rectype) (jrt_update[rectype] & (GUPDREC | UUPDREC))
+#define IS_VALID_RECTYPES_RANGE(rectype) ((JRT_BAD < rectype) && (JRT_RECTYPES > rectype))
+#define IS_REPLICATED(rectype) (jrt_is_replicated[rectype])
+#define IS_FIXED_SIZE(rectype) (jrt_fixed_size[rectype])
+#define IS_SET(rectype) (jrt_update[rectype] & SETREC)
+#define IS_KILL(rectype) (jrt_update[rectype] & KILLREC)
+#define IS_ZKILL(rectype) (jrt_update[rectype] & ZKILLREC)
+#define IS_ZTWORM(rectype) (jrt_update[rectype] & ZTWORMREC)
+#define IS_LGTRIG(rectype) (jrt_update[rectype] & LGTRIGREC)
+#define IS_ZTRIG(rectype) (jrt_update[rectype] & ZTRIGREC)
+#define IS_KILL_ZKILL(rectype) (jrt_update[rectype] & (KILLREC | ZKILLREC))
+#define IS_KILL_ZKILL_ZTRIG(rectype) (jrt_update[rectype] & (KILLREC | ZKILLREC | ZTRIGREC))
+#define IS_SET_KILL_ZKILL_ZTRIG(rectype) (jrt_update[rectype] & (SET_KILL_ZKILL_MASK | ZTRIGREC))
+#define IS_SET_KILL_ZKILL_ZTWORM(rectype) (jrt_update[rectype] & SET_KILL_ZKILL_ZTWORM_MASK)
+#define IS_SET_KILL_ZKILL_ZTWORM_LGTRIG(rectype) (jrt_update[rectype] & SET_KILL_ZKILL_ZTWORM_LGTRIG_MASK)
+#define IS_SET_KILL_ZKILL_ZTWORM_ZTRIG(rectype) (jrt_update[rectype] & SET_KILL_ZKILL_ZTWORM_ZTRIG_MASK)
+#define IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype) (jrt_update[rectype] & SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG_MASK)
+#define IS_FENCED(rectype) (jrt_update[rectype] & FENCE_MASK)
+#define IS_TP(rectype) (jrt_update[rectype] & TPREC_MASK)
+#define IS_ZTP(rectype) (jrt_update[rectype] & ZTPREC_MASK)
+#define IS_COM(rectype) (jrt_update[rectype] & (TCOMREC | ZTCOMREC))
+#define IS_FUPD(rectype) (jrt_update[rectype] & FUPDREC)
+#define IS_GUPD(rectype) (jrt_update[rectype] & GUPDREC)
+#define IS_TUPD(rectype) (jrt_update[rectype] & TUPDREC)
+#define IS_UUPD(rectype) (jrt_update[rectype] & UUPDREC)
+#define IS_FUPD_TUPD(rectype) (jrt_update[rectype] & (FUPDREC | TUPDREC))
+#define IS_GUPD_UUPD(rectype) (jrt_update[rectype] & (GUPDREC | UUPDREC))
#ifdef GTM_TRIGGER
# define IS_VALID_JRECTYPE(rectype) IS_VALID_RECTYPES_RANGE(rectype)
#else /* On trigger non-supporting platforms, it is an error if a ZTWORM or ZTRIG rectype is seen. */
-# define IS_VALID_JRECTYPE(rectype) (IS_VALID_RECTYPES_RANGE(rectype) && !IS_ZTWORM(rectype) && !IS_ZTRIG(rectype))
+# define IS_VALID_JRECTYPE(rectype) (IS_VALID_RECTYPES_RANGE(rectype) && !IS_ZTWORM(rectype) \
+ && !IS_LGTRIG(rectype) && !IS_ZTRIG(rectype))
#endif
#define GET_REC_FENCE_TYPE(rectype) (!IS_FENCED(rectype)) ? NOFENCE : (IS_TP(rectype)) ? TPFENCE : ZTPFENCE
-#define REC_HAS_TOKEN_SEQ(rectype) (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype) || IS_COM(rectype) \
+#define REC_HAS_TOKEN_SEQ(rectype) (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype) || IS_COM(rectype) \
|| (JRT_EPOCH == (rectype)) || (JRT_EOF == (rectype)) \
|| (JRT_NULL == (rectype)))
diff --git a/sr_port/jnl_write.c b/sr_port/jnl_write.c
index fe26659..a35515d 100644
--- a/sr_port/jnl_write.c
+++ b/sr_port/jnl_write.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2012 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -58,6 +58,7 @@ STATICDEF int jnl_write_recursion_depth;
#endif
+error_def(ERR_JNLEXTEND);
error_def(ERR_JNLWRTNOWWRTR);
error_def(ERR_JNLWRTDEFER);
@@ -127,80 +128,100 @@ error_def(ERR_JNLWRTDEFER);
JB->blocked = 0; \
}
-#define DO_JNL_FILE_EXTEND_IF_NEEDED(JREC_LEN, JB, LCL_FREEADDR, CSA, RECTYPE, BLK_PTR, JFB, REG, JPC, JNL_REC) \
-{ \
- int4 jrec_len_padded; \
- \
- GBLREF boolean_t in_jnl_file_autoswitch; \
- \
- /* Before writing a journal record, check if we have some padding space \
- * to close the journal file in case we are on the verge of an autoswitch. \
- * If we are about to autoswitch the journal file at this point, dont \
- * do the padding check since the padding space has already been checked \
- * in jnl_write calls before this autoswitch invocation. We can safely \
- * write the input record without worrying about autoswitch limit overflow. \
- */ \
- jrec_len_padded = JREC_LEN; \
- if (!in_jnl_file_autoswitch) \
- jrec_len_padded = JREC_LEN + JNL_FILE_TAIL_PRESERVE; \
- if (JB->filesize < DISK_BLOCKS_SUM(LCL_FREEADDR, jrec_len_padded)) /* not enough room in jnl file, extend it */ \
- { /* We should never reach here if we are called from t_end/tp_tend. We check that by using the fact that \
- * early_tn is different from curr_tn in the t_end/tp_tend case. The only exception is wcs_recover which \
- * also sets these to be different in case of writing an INCTN record. For this case though it is okay to \
- * extend/autoswitch the file. So allow that. \
- */ \
- assertpro((CSA->ti->early_tn == CSA->ti->curr_tn) || (JRT_INCTN == RECTYPE)); \
- assert(!IS_REPLICATED(RECTYPE)); /* all replicated jnl records should have gone through t_end/tp_tend */ \
- assert(jrt_fixed_size[RECTYPE]); /* this is used later in re-computing checksums */ \
- assert(NULL == BLK_PTR); /* as otherwise it is a PBLK or AIMG record which is of variable record \
- * length that conflicts with the immediately above assert. \
- */ \
- assert(NULL == JFB); /* as otherwise it is a logical record with formatted journal records which \
- * is of variable record length (conflicts with the jrt_fixed_size assert). \
- */ \
- assertpro(!in_jnl_file_autoswitch); /* avoid recursion of jnl_file_extend */ \
- if (SS_NORMAL != jnl_flush(REG)) \
- { \
- assert(NOJNL == JPC->channel); /* jnl file lost */ \
- DEBUG_ONLY(jnl_write_recursion_depth--); \
- return; /* let the caller handle the error */ \
- } \
- assert(LCL_FREEADDR == JB->dskaddr); \
- if (EXIT_ERR == jnl_file_extend(JPC, JREC_LEN)) /* if extension fails, not much we can do */ \
- { \
- DEBUG_ONLY(jnl_write_recursion_depth--); \
- assert(FALSE); \
- return; \
- } \
- if (0 == JPC->pini_addr) \
- { /* This can happen only if jnl got switched in jnl_file_extend above. \
- * Write a PINI record in the new journal file and then continue writing the input record. \
- * Basically we need to redo the processing in jnl_write because a lot of the local variables \
- * have changed state (e.g. JB->freeaddr etc.). So we instead call jnl_write() \
- * recursively and then return immediately. \
- */ \
- jnl_put_jrt_pini(CSA); \
- assertpro(JPC->pini_addr); /* should have been set in "jnl_put_jrt_pini" */ \
- if (JRT_PINI != RECTYPE) \
- { \
- JNL_REC->prefix.pini_addr = JPC->pini_addr; \
- /* Checksum needs to be recomputed since prefix.pini_addr is changed in above statement */ \
- JNL_REC->prefix.checksum = INIT_CHECKSUM_SEED; \
- JNL_REC->prefix.checksum = compute_checksum(INIT_CHECKSUM_SEED, \
- (uint4 *)JNL_REC, JNL_REC->prefix.forwptr); \
- jnl_write(JPC, RECTYPE, JNL_REC, NULL, NULL); \
- } \
- DEBUG_ONLY(jnl_write_recursion_depth--); \
- return; \
- } \
- } \
+int jnl_write_extend_if_needed(int4 jrec_len, jnl_buffer_ptr_t jb, uint4 lcl_freeaddr, sgmnt_addrs *csa,
+ enum jnl_record_type rectype, blk_hdr_ptr_t blk_ptr, jnl_format_buffer *jfb,
+ gd_region *reg, jnl_private_control *jpc, jnl_record *jnl_rec);
+
+#define DO_JNL_FILE_EXTEND_IF_NEEDED(JREC_LEN, JB, LCL_FREEADDR, CSA, RECTYPE, BLK_PTR, JFB, REG, JPC, JNL_REC) \
+MBSTART { \
+ if (0 != jnl_write_extend_if_needed(JREC_LEN, JB, LCL_FREEADDR, CSA, RECTYPE, BLK_PTR, JFB, \
+ REG, JPC, JNL_REC)) \
+ return; /* return from calling routine */ \
+} MBEND
+
+int jnl_write_extend_if_needed(int4 jrec_len, jnl_buffer_ptr_t jb, uint4 lcl_freeaddr, sgmnt_addrs *csa,
+ enum jnl_record_type rectype, blk_hdr_ptr_t blk_ptr, jnl_format_buffer *jfb,
+ gd_region *reg, jnl_private_control *jpc, jnl_record *jnl_rec)
+{
+ int4 jrec_len_padded;
+ int4 blocks_needed;
+ boolean_t do_extend;
+
+ /* Before writing a journal record, check if we have some padding space
+ * to close the journal file in case we are on the verge of an autoswitch.
+ * If we are about to autoswitch the journal file at this point, dont
+ * do the padding check since the padding space has already been checked
+ * in jnl_write calls before this autoswitch invocation. We can safely
+ * write the input record without worrying about autoswitch limit overflow.
+ */
+ jrec_len_padded = jrec_len;
+ if (!in_jnl_file_autoswitch)
+ jrec_len_padded = jrec_len + JNL_FILE_TAIL_PRESERVE;
+ blocks_needed = DISK_BLOCKS_SUM(lcl_freeaddr, jrec_len_padded);
+ do_extend = jb->last_eof_written || (jb->filesize < blocks_needed);
+ if (do_extend)
+ { /* not enough room in jnl file, extend it */
+ /* We should never reach here if we are called from t_end/tp_tend. We check that by using the fact that
+ * early_tn is different from curr_tn in the t_end/tp_tend case. The only exception is wcs_recover which
+ * also sets these to be different in case of writing an INCTN record. For this case though it is okay to
+ * extend/autoswitch the file. So allow that.
+ */
+ if (!jb->last_eof_written)
+ {
+ assertpro((csa->ti->early_tn == csa->ti->curr_tn) || (JRT_INCTN == rectype));
+ assert(!IS_REPLICATED(rectype)); /* all replicated jnl records should have gone through t_end/tp_tend */
+ assert(jrt_fixed_size[rectype]); /* this is used later in re-computing checksums */
+ }
+ assert(NULL == blk_ptr); /* as otherwise it is a PBLK or AIMG record which is of variable record
+ * length that conflicts with the immediately above assert.
+ */
+ assert(NULL == jfb); /* as otherwise it is a logical record with formatted journal records which
+ * is of variable record length (conflicts with the jrt_fixed_size assert).
+ */
+ assertpro(!in_jnl_file_autoswitch); /* avoid recursion of jnl_file_extend */
+ if (SS_NORMAL != jnl_flush(reg))
+ {
+ assert(NOJNL == jpc->channel); /* jnl file lost */
+ DEBUG_ONLY(jnl_write_recursion_depth--);
+ return 1; /* let the caller handle the error */
+ }
+ assert(lcl_freeaddr == jb->dskaddr);
+ if (EXIT_ERR == jnl_file_extend(jpc, jrec_len))
+ {
+ DEBUG_ONLY(jnl_write_recursion_depth--);
+ return 1;
+ }
+ assert(!jb->last_eof_written);
+ if (0 == jpc->pini_addr)
+ { /* This can happen only if jnl got switched in jnl_file_extend above.
+ * Write a PINI record in the new journal file and then continue writing the input record.
+ * Basically we need to redo the processing in jnl_write because a lot of the local variables
+ * have changed state (e.g. JB->freeaddr etc.). So we instead call jnl_write()
+ * recursively and then return immediately.
+ */
+ jnl_put_jrt_pini(csa);
+ assertpro(jpc->pini_addr); /* should have been set in "jnl_put_jrt_pini" */
+ if (JRT_PINI != rectype)
+ {
+ jnl_rec->prefix.pini_addr = jpc->pini_addr;
+ /* Checksum needs to be recomputed since prefix.pini_addr is changed in above statement */
+ jnl_rec->prefix.checksum = INIT_CHECKSUM_SEED;
+ jnl_rec->prefix.checksum = compute_checksum(INIT_CHECKSUM_SEED,
+ (uint4 *)jnl_rec, jnl_rec->prefix.forwptr);
+ jnl_write(jpc, rectype, jnl_rec, NULL, NULL);
+ }
+ DEBUG_ONLY(jnl_write_recursion_depth--);
+ return 1;
+ }
+ }
+ return 0;
}
/* jpc : Journal private control
* rectype : Record type
* jnl_rec : This contains fixed part of a variable size record or the complete fixed size records.
* blk_ptr : For JRT_PBLK and JRT_AIMG this has the block image
- * jfb : For SET/KILL/ZKILL/ZTWORM records entire record is formatted in this.
+ * jfb : For SET/KILL/ZKILL/ZTWORM/LGTRIG/ZTRIG records entire record is formatted in this.
* For JRT_PBLK and JRT_AIMG it contains partial records
*/
void jnl_write(jnl_private_control *jpc, enum jnl_record_type rectype, jnl_record *jnl_rec, blk_hdr_ptr_t blk_ptr,
@@ -258,9 +279,10 @@ void jnl_write(jnl_private_control *jpc, enum jnl_record_type rectype, jnl_recor
/* Do high-level check on rlen */
assert(rlen <= jb->max_jrec_len);
/* Do fine-grained checks on rlen */
- GTMTRIG_ONLY(assert(!IS_ZTWORM(rectype) || (MAX_ZTWORM_JREC_LEN >= rlen));) /* ZTWORMHOLE */
- assert(!IS_SET_KILL_ZKILL_ZTRIG(rectype) || (JNL_MAX_SET_KILL_RECLEN(csd) >= rlen)); /* SET, KILL, ZKILL */
- assert((NULL == blk_ptr) || (JNL_MAX_PBLK_RECLEN(csd) >= rlen)); /* PBLK and AIMG */
+ GTMTRIG_ONLY(assert(!IS_ZTWORM(rectype) || (MAX_ZTWORM_JREC_LEN >= rlen));) /* ZTWORMHOLE */
+ GTMTRIG_ONLY(assert(!IS_LGTRIG(rectype) || (MAX_LGTRIG_JREC_LEN >= rlen));) /* LGTRIG */
+ assert(!IS_SET_KILL_ZKILL_ZTRIG(rectype) || (JNL_MAX_SET_KILL_RECLEN(csd) >= rlen)); /* SET, KILL, ZKILL, ZTRIG */
+ assert((NULL == blk_ptr) || (JNL_MAX_PBLK_RECLEN(csd) >= rlen)); /* PBLK and AIMG */
jb->bytcnt += rlen;
assert (0 == rlen % JNL_REC_START_BNDRY);
rlen_with_align = rlen + (int4)MIN_ALIGN_RECLEN;
@@ -379,7 +401,7 @@ void jnl_write(jnl_private_control *jpc, enum jnl_record_type rectype, jnl_recor
tmp_csum1 = jnl_get_checksum((uint4 *)blk_ptr, NULL, jnl_rec->jrec_pblk.bsiz);
COMPUTE_PBLK_CHECKSUM(tmp_csum1, &jnl_rec->jrec_pblk, tmp_csum2, tmp_csum1);
assert(checksum == tmp_csum1);
- } else if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ } else if (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype))
{
COMPUTE_COMMON_CHECKSUM(tmp_csum2, jnl_rec->prefix);
mumps_node_ptr = jfb->buff + FIXED_UPD_RECLEN;
@@ -508,7 +530,7 @@ void jnl_write(jnl_private_control *jpc, enum jnl_record_type rectype, jnl_recor
else
{
# ifdef GTM_CRYPT
- if (csd->is_encrypted && IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (csd->is_encrypted && IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype))
ptr = jfb->alt_buff;
else
# endif
@@ -519,12 +541,29 @@ void jnl_write(jnl_private_control *jpc, enum jnl_record_type rectype, jnl_recor
DEBUG_ONLY(jgbl.cu_jnl_index++;)
jnlpool_size = temp_jnlpool_ctl->jnlpool_size;
dstlen = jnlpool_size - temp_jnlpool_ctl->write;
- if (rlen <= dstlen) /* dstlen >= rlen (most frequent case) */
+ if (rlen <= dstlen) /* dstlen >= rlen (most frequent case) */
memcpy(jnldata_base + temp_jnlpool_ctl->write, ptr, rlen);
- else /* dstlen < rlen */
+ else if (rlen <= jnlpool_size) /* dstlen < rlen <= jnlpool_size */
{
memcpy(jnldata_base + temp_jnlpool_ctl->write, ptr, dstlen);
memcpy(jnldata_base, ptr + dstlen, rlen - dstlen);
+ } else /* dstlen <= jnlpool_size < rlen */
+ { /* Copy just the last "jnlpool_size" bytes of the journal record (which could be arbitrarily large)
+ * onto the journal pool. Adjust pointers as appropriate. Note that this transaction can never be
+ * read from the journal pool (because it does not completely fit in) but we still need to maintain
+ * contiguity of jnl-seqnos in the journal pool. Note we could probably copy 0s in the journal pool
+ * instead of the last "jnlpool_size" bytes and still things should work as well but we copy valid
+ * data just in case it helps in debug situations.
+ */
+ ptr = ptr + rlen - jnlpool_size;
+ temp_jnlpool_ctl->write += rlen % jnlpool_size;
+ if (temp_jnlpool_ctl->write >= jnlpool_size)
+ temp_jnlpool_ctl->write -= jnlpool_size;
+ assert(temp_jnlpool_ctl->write < jnlpool_size);
+ dstlen = jnlpool_size - temp_jnlpool_ctl->write;
+ memcpy(jnldata_base + temp_jnlpool_ctl->write, ptr, dstlen);
+ memcpy(jnldata_base, ptr + dstlen, jnlpool_size - dstlen);
+ rlen = 0;
}
temp_jnlpool_ctl->write += rlen;
if (temp_jnlpool_ctl->write >= jnlpool_size)
diff --git a/sr_port/jnl_write_eof_rec.c b/sr_port/jnl_write_eof_rec.c
index 27c0a1b..697fee3 100644
--- a/sr_port/jnl_write_eof_rec.c
+++ b/sr_port/jnl_write_eof_rec.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2012 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -39,7 +39,7 @@ void jnl_write_eof_rec(sgmnt_addrs *csa, struct_jrec_eof *eof_record)
assert(csa->now_crit);
jpc = csa->jnl;
- assert(0 != jpc->pini_addr);
+ assert((0 != jpc->pini_addr) || (jpc->jnl_buff->freeaddr > jpc->jnl_buff->filesize - JNL_FILE_TAIL_PRESERVE));
eof_record->prefix.jrec_type = JRT_EOF;
eof_record->prefix.forwptr = eof_record->suffix.backptr = EOF_RECLEN;
eof_record->suffix.suffix_code = JNL_REC_SUFFIX_CODE;
diff --git a/sr_port/jnl_write_epoch_rec.c b/sr_port/jnl_write_epoch_rec.c
index 05b4995..2475e0a 100644
--- a/sr_port/jnl_write_epoch_rec.c
+++ b/sr_port/jnl_write_epoch_rec.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -100,16 +100,6 @@ void jnl_write_epoch_rec(sgmnt_addrs *csa)
epoch_record.strm_seqno[idx] = csd->strm_reg_seqno[idx];
/* If MUPIP JOURNAL -ROLLBACK, might need to do additional processing. See macro definition for comments */
MUR_ADJUST_STRM_REG_SEQNO_IF_NEEDED(csd, epoch_record.strm_seqno);
-# ifdef DEBUG
- if (jgbl.mur_rollback)
- { /* Assert that the unified jnl_seqno is always >= the individual stream seqnos. While this is not
- * guaranteed to be true if users play with the seqnos in the db file header, it is mostly true
- * and hence a good indicator to have particularly since it catches code issues right away.
- */
- for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)
- assert(epoch_record.strm_seqno[idx] <= epoch_record.jnl_seqno);
- }
-# endif
} else if (REPL_ALLOWED(csd))
{
epoch_record.jnl_seqno = csd->reg_seqno; /* Note we cannot use jnlpool_ctl->jnl_seqno since
@@ -172,4 +162,5 @@ void jnl_write_epoch_rec(sgmnt_addrs *csa)
epoch_record.filler = 0;
epoch_record.prefix.checksum = compute_checksum(INIT_CHECKSUM_SEED, (uint4 *)&epoch_record, SIZEOF(struct_jrec_epoch));
jnl_write(jpc, JRT_EPOCH, (jnl_record *)&epoch_record, NULL, NULL);
+ jb->post_epoch_freeaddr = jb->freeaddr;
}
diff --git a/sr_port/jnl_write_logical.c b/sr_port/jnl_write_logical.c
index ea1e0b8..88a0a0a 100644
--- a/sr_port/jnl_write_logical.c
+++ b/sr_port/jnl_write_logical.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -59,7 +59,7 @@ void jnl_write_logical(sgmnt_addrs *csa, jnl_format_buffer *jfb, uint4 com_csum)
assert((0 != jpc->pini_addr) || REPL_WAS_ENABLED(csa));
assert(jgbl.gbl_jrec_time || REPL_WAS_ENABLED(csa));
assert(csa->now_crit);
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(jfb->rectype) || (JRT_NULL == jfb->rectype));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(jfb->rectype) || (JRT_NULL == jfb->rectype));
assert(!IS_ZTP(jfb->rectype));
jrec = (struct_jrec_upd *)jfb->buff;
assert(OFFSETOF(struct_jrec_null, prefix) == OFFSETOF(struct_jrec_upd, prefix));
@@ -76,14 +76,12 @@ void jnl_write_logical(sgmnt_addrs *csa, jnl_format_buffer *jfb, uint4 com_csum)
assert(OFFSETOF(struct_jrec_null, strm_seqno) == OFFSETOF(struct_jrec_upd, strm_seqno));
assert(SIZEOF(jrec_null->strm_seqno) == SIZEOF(jrec->strm_seqno));
jrec->strm_seqno = jnl_fence_ctl.strm_seqno;
- /*update checksum below*/
+ /* update checksum below */
if(JRT_NULL != jrec->prefix.jrec_type)
{
COMPUTE_LOGICAL_REC_CHECKSUM(jfb->checksum, jrec, com_csum, jrec->prefix.checksum);
- }
- else
+ } else
jrec->prefix.checksum = compute_checksum(INIT_CHECKSUM_SEED, (uint4 *)jrec, SIZEOF(struct_jrec_null));
-
# ifdef GTM_CRYPT
if (csa->hdr->is_encrypted && REPL_ALLOWED(csa))
{
diff --git a/sr_port/jnl_write_poolonly.c b/sr_port/jnl_write_poolonly.c
index 212555d..9a398f0 100644
--- a/sr_port/jnl_write_poolonly.c
+++ b/sr_port/jnl_write_poolonly.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2007, 2010 Fidelity Information Services, Inc *
+ * Copyright 2007, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -44,6 +44,9 @@ GBLREF jnlpool_addrs jnlpool;
GBLREF jnlpool_ctl_ptr_t jnlpool_ctl;
GBLREF jnl_gbls_t jgbl;
+error_def(ERR_JNLWRTDEFER);
+error_def(ERR_JNLWRTNOWWRTR);
+
/* This function does a subset of what "jnl_write" does. While "jnl_write" writes the journal record to the journal buffer,
* journal file and journal pool, this function writes the journal records ONLY TO the journal pool. This function should
* be invoked only if replication state is WAS_ON (repl_was_open) and journaling state is jnl_closed.
@@ -68,9 +71,6 @@ void jnl_write_poolonly(jnl_private_control *jpc, enum jnl_record_type rectype,
DEBUG_ONLY(uint4 lcl_dskaddr;)
uchar_ptr_t tmp_buff;
- error_def(ERR_JNLWRTNOWWRTR);
- error_def(ERR_JNLWRTDEFER);
-
assert(NULL != jnl_rec);
assert(rectype > JRT_BAD && rectype < JRT_RECTYPES && JRT_ALIGN != rectype);
assert(jrt_is_replicated[rectype]);
@@ -90,7 +90,7 @@ void jnl_write_poolonly(jnl_private_control *jpc, enum jnl_record_type rectype,
if (jrt_fixed_size[rectype])
jnlrecptr = (uchar_ptr_t)jnl_rec;
# ifdef GTM_CRYPT
- else if(csa->hdr->is_encrypted && IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ else if (csa->hdr->is_encrypted && IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype))
jnlrecptr = (uchar_ptr_t)jfb->alt_buff;
# endif
else
diff --git a/sr_port/lastchance1.c b/sr_port/lastchance1.c
index a2e103a..14df25d 100644
--- a/sr_port/lastchance1.c
+++ b/sr_port/lastchance1.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -17,6 +17,9 @@
#include "error.h"
#include "gv_rundown.h"
#include "util.h"
+#ifdef GTM_CRYPT
+# include "gtmcrypt.h"
+#endif
GBLREF int4 exi_condition;
GBLREF boolean_t created_core;
@@ -45,6 +48,7 @@ CONDITION_HANDLER(lastchance1)
REVERT;
ESTABLISH(lastchance3);
io_rundown(NORMAL_RUNDOWN);
+ GTMCRYPT_ONLY(GTMCRYPT_CLOSE;)
REVERT;
if (DUMPABLE && !SUPPRESS_DUMP)
DUMP_CORE;
diff --git a/sr_port/lclcol.mpt b/sr_port/lclcol.mpt
index a994d65..23e3ec2 100644
--- a/sr_port/lclcol.mpt
+++ b/sr_port/lclcol.mpt
@@ -1,25 +1,25 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; ;
-; Copyright 2001, 2012 Fidelity Information Services, Inc ;
-; ;
-; This source code contains the intellectual property ;
-; of its copyright holder(s), and is made available ;
-; under a license. If you do not know the terms of ;
-; the license, please stop and do not read further. ;
-; ;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; ;
+; Copyright 2001, 2014 Fidelity Information Services, Inc ;
+; ;
+; This source code contains the intellectual property ;
+; of its copyright holder(s), and is made available ;
+; under a license. If you do not know the terms of ;
+; the license, please stop and do not read further. ;
+; ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%lclcol ; ; ; Local Variable Collation Control
;
-get() q $v("YLCT")
-getncol() q $v("YLCT","ncol") ; return null collation order
+get() quit $view("YLCT")
+getncol() quit $view("YLCT","ncol") ; return null collation order
;
-getnct() q $v("YLCT","nct") ; return numeric collation type
+getnct() quit $view("YLCT","nct") ; return numeric collation type
;
set(lct,ncol,nct)
- n ok,$et
- s $et="s $ec="""" s ok=0",ok=1
- s:'$data(lct) lct=-1
- s:'$data(ncol) ncol=-1
- s:'$data(nct) nct=-1
- v:ok "YLCT":lct:ncol:nct
- q ok
+ new $etrap
+ set $etrap="set $ecode="""" quit 0"
+ set:""=$get(lct) lct=$view("YLCT")
+ set:""=$get(ncol) ncol=$view("YLCT","ncol")
+ set:""=$get(nct) nct=$view("YLCT","nct")
+ if (lct'=$view("YLCT"))!(ncol'=$view("YLCT","ncol"))!(nct'=$view("YLCT","nct")) view "YLCT":lct:ncol:nct
+ quit 1
diff --git a/sr_port/lke.hlp b/sr_port/lke.hlp
index ba71780..c110308 100644
--- a/sr_port/lke.hlp
+++ b/sr_port/lke.hlp
@@ -555,7 +555,7 @@
1 Copyright
Copyright
- Copyright 2013
+ Copyright 2014
Fidelity Information Services, Inc. All rights reserved.
@@ -576,7 +576,7 @@
**Note**
- This help file is a concise representation of revision V6.1-000 of the
+ This help file is a concise representation of revision V6.2-000 of the
UNIX Administration and Operations Guide. To obtain a copy of the current
revision, go to www.fis-gtm.com and then click on the User Documentation
tab.
diff --git a/sr_port/lookup_variable_htent.c b/sr_port/lookup_variable_htent.c
index 53a97ec..98aba14 100644
--- a/sr_port/lookup_variable_htent.c
+++ b/sr_port/lookup_variable_htent.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,8 +12,8 @@
#include "mdef.h"
#include "gtm_stdio.h"
-#include "gtm_string.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "gdsroot.h"
#include "gtm_facility.h"
@@ -31,7 +31,6 @@ GBLREF stack_frame *frame_pointer;
ht_ent_mname *lookup_variable_htent(unsigned int x)
{
ht_ent_mname *tabent;
- mident_fixed varname;
boolean_t added;
assert(x < frame_pointer->vartab_len);
@@ -40,11 +39,10 @@ ht_ent_mname *lookup_variable_htent(unsigned int x)
if (NULL == tabent->value)
{
assert(added); /* Should never be a valid name without an lv */
-#ifdef DEBUG_REFCNT
- memset(varname.c, '\0', SIZEOF(varname));
- memcpy(varname.c, tabent->key.var_name.addr, tabent->key.var_name.len);
- DBGRFCT((stderr, "lookup_variable_htent: Allocating lv_val for variable '%s'\n", varname.c));
-#endif
+# ifdef DEBUG_REFCNT
+ DBGRFCT((stderr, "\nlookup_variable_htent: Allocating lv_val for variable '%.*s'\n", tabent->key.var_name.len,
+ tabent->key.var_name.addr));
+# endif
lv_newname(tabent, curr_symval);
}
assert(NULL != LV_GET_SYMVAL((lv_val *)tabent->value));
diff --git a/sr_port/lv_getslot.c b/sr_port/lv_getslot.c
index f7c4157..129a50f 100644
--- a/sr_port/lv_getslot.c
+++ b/sr_port/lv_getslot.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,6 +13,7 @@
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "gdsroot.h"
#include "gtm_facility.h"
@@ -21,7 +22,17 @@
#include "gdsfhead.h"
#include "caller_id.h"
#include "alias.h"
+#include <rtnhdr.h>
+#include "stack_frame.h"
+GBLREF stack_frame *frame_pointer;
+GBLREF symval *curr_symval;
+
+/* Allocate a local variable slot (lv_val) in an lv_blk that contains one or more unallocated entries.
+ *
+ * Argument: symval pointer to allocate the lv_val from.
+ * Returns: allocated lv_val pointer.
+ */
lv_val *lv_getslot(symval *sym)
{
lv_blk *p,*q;
@@ -31,7 +42,7 @@ lv_val *lv_getslot(symval *sym)
numElems = MAXUINT4; /* maximum value */
if (lv = sym->lv_flist)
{
- assert(NULL == LV_PARENT(lv)); /* stp_gcol relies on this for correct garbage collection */
+ assert(NULL == LV_PARENT(lv)); /* stp_gcol relies on this for correct garbage collection */
sym->lv_flist = (lv_val *)lv->ptrs.free_ent.next_free;
} else
{
@@ -57,12 +68,11 @@ lv_val *lv_getslot(symval *sym)
p->numUsed++;
break;
}
- assert(numElems >= p->numAlloc);
- DEBUG_ONLY(numElems = p->numAlloc);
}
}
assert(lv);
- DBGRFCT((stderr, ">> lv_getslot(): Allocating new lv_val at 0x"lvaddr" by routine 0x"lvaddr"\n", lv, caller_id()));
+ DBGRFCT((stderr, "\n>> lv_getslot(): Allocating new lv_val at 0x"lvaddr" by routine 0x"lvaddr" at mpc 0x"lvaddr
+ " for symval 0x"lvaddr" (curr_symval: 0x"lvaddr")\n", lv, caller_id(), frame_pointer->mpc, sym, curr_symval));
return lv;
}
diff --git a/sr_port/lv_kill.c b/sr_port/lv_kill.c
index 5539a74..844a30d 100644
--- a/sr_port/lv_kill.c
+++ b/sr_port/lv_kill.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "gdsroot.h"
#include "gtm_facility.h"
@@ -21,8 +22,9 @@
#include "gdsbt.h"
#include "gdsfhead.h"
#include "alias.h"
+#include <rtnhdr.h>
+#include "stack_frame.h"
-GBLREF lv_val *active_lv;
GBLREF uint4 dollar_tlevel;
void lv_kill(lv_val *lv, boolean_t dotpsave, boolean_t do_subtree)
@@ -32,8 +34,7 @@ void lv_kill(lv_val *lv, boolean_t dotpsave, boolean_t do_subtree)
boolean_t is_base_var;
symval *sym;
- active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful. clear active_lv to avoid later
- cleanup problems */
+ SET_ACTIVE_LV(NULL, FALSE, actlv_lv_kill); /* Clear active_lv to avoid later cleanup problems */
if (lv)
{
is_base_var = LV_IS_BASE_VAR(lv);
diff --git a/sr_port/lv_killarray.c b/sr_port/lv_killarray.c
index 5cc2c40..3b9ce15 100644
--- a/sr_port/lv_killarray.c
+++ b/sr_port/lv_killarray.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "gdsroot.h"
#include "gtm_facility.h"
@@ -21,6 +22,8 @@
#include "gdsbt.h"
#include "gdsfhead.h"
#include "alias.h"
+#include <rtnhdr.h>
+#include "stack_frame.h"
/* Note it is important that callers of this routine make sure that the pointer that is passed as
* an argument is removed from the lv_val it came from prior to the call. This prevents arrays
diff --git a/sr_port/lv_newblock.c b/sr_port/lv_newblock.c
index b04379e..670c783 100644
--- a/sr_port/lv_newblock.c
+++ b/sr_port/lv_newblock.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_string.h"
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "gtm_malloc.h"
#include "lv_val.h"
#include "gdsroot.h"
diff --git a/sr_port/lv_newname.c b/sr_port/lv_newname.c
index a9de491..f827de5 100644
--- a/sr_port/lv_newname.c
+++ b/sr_port/lv_newname.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "mv_stent.h"
@@ -37,29 +38,25 @@ void lv_newname(ht_ent_mname *hte, symval *sym)
lv_val *lv, *var;
tp_frame *tf, *first_tf_saveall;
tp_var *restore_ent;
- DBGRFCT_ONLY(mident_fixed vname;)
assert(hte);
assert(sym);
- lv = lv_getslot(sym);
+ lv = lv_getslot(sym); /* Allocate slot for new variable */
LVVAL_INIT(lv, sym);
- DBGRFCT_ONLY(
- memcpy(vname.c, hte->key.var_name.addr, hte->key.var_name.len);
- vname.c[hte->key.var_name.len] = '\0';
- );
- DBGRFCT((stderr, "lv_newname: Varname '%s' in sym 0x"lvaddr" resetting hte 0x"lvaddr" from 0x"lvaddr" to 0x"lvaddr
- " -- called from 0x"lvaddr"\n\n",
- &vname.c, sym, hte, hte->value, lv, caller_id()));
+ DBGRFCT((stderr, "\nlv_newname: Varname '%.*s' in sym 0x"lvaddr" resetting hte 0x"lvaddr" from 0x"lvaddr" to 0x"lvaddr
+ " -- called from 0x"lvaddr"\n\n", hte->key.var_name.len, hte->key.var_name.addr, sym, hte, hte->value, lv,
+ caller_id()));
hte->value = lv;
- assert(0 < lv->stats.trefcnt);
+ assert(1 == lv->stats.trefcnt);
+ assert(0 == lv->stats.crefcnt);
if (!sym->tp_save_all)
return;
/* Newly encountered variables need to be saved if there is restore all TP frame in effect as they
- need to be restored to an undefined state but we only know about them when we encounter them
- hence this code where new vars are created. We locate the earliest TP frame that has the same symval
- in its tp_frame and save the entry there. This is so var set in later TP frame levels still get restored
- even if the TSTART frame they were created in gets committed.
- */
+ * need to be restored to an undefined state but we only know about them when we encounter them
+ * hence this code where new vars are created. We locate the earliest TP frame that has the same symval
+ * in its tp_frame and save the entry there. This is so var set in later TP frame levels still get restored
+ * even if the TSTART frame they were created in gets committed.
+ */
DEBUG_ONLY(first_tf_saveall = NULL);
for (tf = tp_pointer; (NULL != tf) && (tf->sym == sym); tf = tf->old_tp_frame)
{
@@ -69,6 +66,8 @@ void lv_newname(ht_ent_mname *hte, symval *sym)
assert(first_tf_saveall);
assert(sym == LV_SYMVAL(lv));
var = lv_getslot(sym);
+ DBGRFCT((stderr, "lv_newname: Varname '%.*s' being saved into save_lv 0x"lvaddr" due to located TSTART *\n",
+ hte->key.var_name.len, hte->key.var_name.addr, var));
restore_ent = (tp_var *)malloc(SIZEOF(*restore_ent));
restore_ent->current_value = lv;
restore_ent->save_value = var;
diff --git a/sr_port/lv_tree.c b/sr_port/lv_tree.c
index 98cc445..b76e4a6 100644
--- a/sr_port/lv_tree.c
+++ b/sr_port/lv_tree.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2011, 2012 Fidelity Information Services, Inc *
+ * Copyright 2011, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -26,6 +26,15 @@
#include "promodemo.h" /* for "promote" & "demote" prototype */
#include "gtmio.h"
#include "have_crit.h"
+#include "gdsroot.h"
+#include "gdsblk.h"
+#include "gtm_facility.h"
+#include "fileinfo.h"
+#include "gdsbt.h"
+#include "gdsfhead.h"
+#include <rtnhdr.h>
+#include "stack_frame.h"
+#include "alias.h"
#define LV_TREE_INIT_ALLOC 4
#define LV_TREENODE_INIT_ALLOC 16
@@ -622,13 +631,13 @@ lvTreeNode *lvAvlTreeNodeCollatedNext(lvTreeNode *node)
}
/* Function to clone an avl tree (used by the LV_TREE_CLONE macro). Uses recursion to descend the tree. */
-lvTreeNode *lvAvlTreeCloneSubTree(lvTreeNode *node, lvTree *lvt, lvTreeNode *avl_parent)
+lvTreeNode *lvAvlTreeCloneSubTree(lvTreeNode *node, lvTree *lvt, lvTreeNode *avl_parent, boolean_t refCntMaint)
{
lvTreeNodeVal *dupVal;
lvTreeNode *cloneNode, *left, *right;
lvTreeNode *leftSubTree, *rightSubTree;
lvTree *lvt_child;
- lv_val *base_lv;
+ lv_val *base_lv, *cntnr_lv;
assert(NULL != node);
cloneNode = lvtreenode_getslot(LVT_GET_SYMVAL(lvt));
@@ -654,6 +663,15 @@ lvTreeNode *lvAvlTreeCloneSubTree(lvTreeNode *node, lvTree *lvt, lvTreeNode *avl
assert(OFFSETOF(lvTreeNode, avl_right) + SIZEOF(cloneNode->avl_right) == OFFSETOF(lvTreeNode, avl_parent));
assert(OFFSETOF(lvTreeNode, avl_parent) + SIZEOF(cloneNode->avl_parent) == SIZEOF(lvTreeNode));
cloneNode->v = node->v;
+ /* If refCntMaint is true, when an alias container is copied, we bump the reference counts of whatever it points to. This
+ * keeps the reference counts correct across TP.
+ */
+ if (refCntMaint && (MV_ALIASCONT & cloneNode->v.mvtype))
+ {
+ cntnr_lv = (lv_val *)cloneNode->v.str.addr;
+ INCR_TREFCNT(cntnr_lv);
+ INCR_CREFCNT(cntnr_lv);
+ }
/* "cloneNode->sbs_child" initialized later */
cloneNode->tree_parent = lvt;
/* cloneNode->key_mvtype/balance/descent_dir/key_len all initialized in one shot */
@@ -668,14 +686,14 @@ lvTreeNode *lvAvlTreeCloneSubTree(lvTreeNode *node, lvTree *lvt, lvTreeNode *avl
base_lv = lvt->base_lv;
if (NULL != lvt_child)
{
- LV_TREE_CLONE(lvt_child, cloneNode, base_lv); /* initializes "cloneNode->sbs_child" */
+ LV_TREE_CLONE(lvt_child, cloneNode, base_lv, refCntMaint); /* initializes "cloneNode->sbs_child" */
} else
cloneNode->sbs_child = NULL;
left = node->avl_left;
- leftSubTree = (NULL != left) ? lvAvlTreeCloneSubTree(left, lvt, cloneNode) : NULL;
+ leftSubTree = (NULL != left) ? lvAvlTreeCloneSubTree(left, lvt, cloneNode, refCntMaint) : NULL;
cloneNode->avl_left = leftSubTree;
right = node->avl_right;
- rightSubTree = (NULL != right) ? lvAvlTreeCloneSubTree(right, lvt, cloneNode) : NULL;
+ rightSubTree = (NULL != right) ? lvAvlTreeCloneSubTree(right, lvt, cloneNode, refCntMaint) : NULL;
cloneNode->avl_right = rightSubTree;
return cloneNode;
}
diff --git a/sr_port/lv_tree.h b/sr_port/lv_tree.h
index 4faa71c..91f3c34 100644
--- a/sr_port/lv_tree.h
+++ b/sr_port/lv_tree.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2011, 2012 Fidelity Information Services, Inc *
+ * Copyright 2011, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -224,7 +224,7 @@ lvTreeNode *lvAvlTreeFirstPostOrder(lvTree *lvt);
lvTreeNode *lvAvlTreeNextPostOrder(lvTreeNode *node);
lvTreeNode *lvAvlTreeKeyCollatedNext(lvTree *lvt, treeKeySubscr *key);
lvTreeNode *lvAvlTreeNodeCollatedNext(lvTreeNode *node);
-lvTreeNode *lvAvlTreeCloneSubTree(lvTreeNode *node, lvTree *lvt, lvTreeNode *avl_parent);
+lvTreeNode *lvAvlTreeCloneSubTree(lvTreeNode *node, lvTree *lvt, lvTreeNode *avl_parent, boolean_t refCntMaint);
#ifdef DEBUG
boolean_t lvTreeIsWellFormed(lvTree *lvt);
@@ -268,7 +268,7 @@ void lvAvlTreeNodeDelete(lvTree *lvt, lvTreeNode *node);
TREE_DEBUG_ONLY(assert(lvTreeIsWellFormed(LVT));) \
}
-#define LV_TREE_CLONE(LVT, SBS_PARENT, BASE_LV) \
+#define LV_TREE_CLONE(LVT, SBS_PARENT, BASE_LV, REFCNTMAINT) \
{ \
lvTree *cloneTree; \
lvTreeNode *avl_root; \
@@ -293,7 +293,7 @@ void lvAvlTreeNodeDelete(lvTree *lvt, lvTreeNode *node);
/* reset clue in cloned tree as source tree pointers are no longer relevant in cloned tree */ \
cloneTree->lastLookup.lastNodeLookedUp = NULL; \
if (NULL != (avl_root = (LVT)->avl_root)) \
- cloneTree->avl_root = lvAvlTreeCloneSubTree(avl_root, cloneTree, NULL); \
+ cloneTree->avl_root = lvAvlTreeCloneSubTree(avl_root, cloneTree, NULL, (REFCNTMAINT)); \
else \
cloneTree->avl_root = NULL; \
}
diff --git a/sr_port/lv_val.h b/sr_port/lv_val.h
index 8093dc1..6203e11 100644
--- a/sr_port/lv_val.h
+++ b/sr_port/lv_val.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -142,9 +142,9 @@
}
/* Increment the cycle for tstarts. Field is compared to same name field in lv_val to signify an lv_val has been seen
- during a given transaction so reference counts are kept correct. If counter wraps, clear all the counters in all
- accessible lv_vals.
-*/
+ * during a given transaction so reference counts are kept correct. If counter wraps, clear all the counters in all
+ * accessible lv_vals.
+ */
#define INCR_TSTARTCYCLE \
{ \
symval *lvlsymtab; \
@@ -160,12 +160,13 @@
lvp->stats.tstartcycle = 0; \
tstartcycle = 1; \
} \
+ DBGRFCT((stderr, "INCR_TSTARTCYCLE: Bumped tstartcycle to 0x%08lx\n", tstartcycle)); \
}
/* Increment the cycle for misc lv tasks. Field is compared to same name field in lv_val to signify an lv_val has been seen
- during a given transaction so reference counts are kept correct. If counter wraps, clear all the counters in all
- accessible lv_vals.
-*/
+ * during a given transaction so reference counts are kept correct. If counter wraps, clear all the counters in all
+ * accessible lv_vals.
+ */
#define INCR_LVTASKCYCLE \
{ \
symval *lvlsymtab; \
@@ -181,12 +182,14 @@
lvp->stats.lvtaskcycle = 0; \
lvtaskcycle = 1; \
} \
+ DBGRFCT((stderr, "INCR_LVTASKCYCLE: Bumped lvtaskcycle to 0x%08lx\n", lvtaskcycle)); \
}
/* Initialize given lv_val (should be of type "lv_val *" and not "lvTreeNode *") */
#define LVVAL_INIT(lv, symvalarg) \
{ \
DBGALS_ONLY(GBLREF boolean_t lvmon_enabled;) \
+ DBGALS_ONLY(GBLREF stack_frame *frame_pointer;) \
assert(MV_SYM == symvalarg->ident); /* ensure above macro is never used to initialize a "lvTreeNode *" */ \
(lv)->v.mvtype = 0; \
(lv)->stats.trefcnt = 1; \
@@ -198,6 +201,8 @@
(lv)->tp_var = NULL; \
LV_CHILD(lv) = NULL; \
LV_SYMVAL(lv) = symvalarg; \
+ DBGALS_ONLY((lv)->stats.init_mpc = frame_pointer->mpc); \
+ DBGALS_ONLY((lv)->stats.init_cpc = CURRENT_PC); /* Currently only works for Linux */ \
}
/* Macro to call lv_var_clone and set the cloned status in the tp_var structure.
@@ -205,32 +210,42 @@
* This is because in case we want to restore the lv, we can then safely move the saved tree
* back to "lv" without then having to readjust the base_lv linked in the "lvTree *" structures beneath
*/
-#define TP_VAR_CLONE(lv) \
-{ \
- lv_val *lcl_savelv; \
- tp_var *lcl_tp_var; \
- \
- assert(LV_IS_BASE_VAR(lv)); \
- lcl_tp_var = (lv)->tp_var; \
- assert(lcl_tp_var); \
- assert(!lcl_tp_var->var_cloned); \
- lcl_savelv = lcl_tp_var->save_value; \
- assert(NULL != lcl_savelv); \
- assert(NULL == LV_CHILD(lcl_savelv)); \
- LV_CHILD(lcl_savelv) = LV_CHILD(lv); \
- lv_var_clone(lcl_savelv, lv); \
- lcl_tp_var->var_cloned = TRUE; \
+#define TP_VAR_CLONE(lv) \
+{ \
+ lv_val *lcl_savelv; \
+ tp_var *lcl_tp_var; \
+ \
+ assert(LV_IS_BASE_VAR(lv)); \
+ lcl_tp_var = (lv)->tp_var; \
+ assert(lcl_tp_var); \
+ assert(!lcl_tp_var->var_cloned); \
+ lcl_savelv = lcl_tp_var->save_value; \
+ assert(NULL != lcl_savelv); \
+ assert(NULL == LV_CHILD(lcl_savelv)); \
+ DBGRFCT((stderr, "\nTP_VAR_CLONE: invoked from %s at line %d\n", __FILE__, __LINE__)); \
+ LV_CHILD(lcl_savelv) = LV_CHILD(lv); \
+ lv_var_clone(lcl_savelv, lv, TRUE); \
+ lcl_tp_var->var_cloned = TRUE; \
+ DBGRFCT((stderr, "TP_VAR_CLONE: complete\n")); \
}
/* Macro to indicate if a given lv_val is an alias or not */
#define IS_ALIASLV(lv) (DBG_ASSERT(LV_IS_BASE_VAR(lv)) ((1 < (lv)->stats.trefcnt) || (0 < (lv)->stats.crefcnt)) \
DEBUG_ONLY(&& assert(IS_PARENT_MV_SYM(lv))))
-
#define LV_NEWBLOCK_INIT_ALLOC 16
#define LV_BLK_GET_BASE(LV_BLK) (((sm_uc_ptr_t)LV_BLK) + SIZEOF(lv_blk))
#define LV_BLK_GET_FREE(LV_BLK, LVBLK_BASE) (&LVBLK_BASE[LV_BLK->numUsed])
+#ifdef DEBUG_ALIAS
+# ifdef __linux__
+/*void * __attribute ((noinline)) __builtin_return_address(unsigned int level); Currently gives a warning we don't need */
+# define CURRENT_PC __builtin_return_address(0)
+# else
+# define CURRENT_PC NULL
+# endif
+#endif
+
typedef struct lv_val_struct
{
mval v; /* Value associated with this lv_val */
@@ -266,6 +281,13 @@ typedef struct lv_val_struct
int4 crefcnt; /* Container reference count */
uint4 tstartcycle; /* Cycle of level 0 tstart command */
uint4 lvtaskcycle; /* Cycle of various lv related tasks */
+# ifdef DEBUG_ALIAS
+ /* Keep these debugging fields inside "stats" so as not to upset the asserts in tp_unwind() and also
+ * since they don't change once set while being allocated anyway.
+ */
+ unsigned char *init_mpc; /* frame_pointer->mpc when LVVAL_INIT() was done */
+ unsigned char *init_cpc; /* current pc so know which C routine did LVVAL_INIT() */
+# endif
} stats;
boolean_t has_aliascont; /* This base var has or had an alias container in it */
boolean_t lvmon_mark; /* This lv_val is being monitored; Used only #ifdef DEBUG_ALIAS */
@@ -280,10 +302,10 @@ typedef struct lv_blk_struct
} lv_blk;
/* When op_xnew creates a symtab, these blocks will describe the vars that were passed through from the
- previous symtab. They need special alias processing. Note we keep our own copy of the key (rather than
- pointing to the hash table entry) since op_xnew processing can cause a hash table expansion and we have
- no good way to update pointers so save the hash values as part of the key to eliminate another lookup.
-*/
+ * previous symtab. They need special alias processing. Note we keep our own copy of the key (rather than
+ * pointing to the hash table entry) since op_xnew processing can cause a hash table expansion and we have
+ * no good way to update pointers so save the hash values as part of the key to eliminate another lookup.
+ */
typedef struct lv_xnew_var_struct
{
struct lv_xnew_var_struct *next;
@@ -296,10 +318,10 @@ typedef struct lv_xnew_var_struct
*/
} lv_xnew_var;
/* While lv_xnew_var_struct are the structures that were explicitly passed through, this is a list of the structures
- that are pointed to by any container vars in any of the passed through vars and any of the vars those point to, etc.
- The objective is to come up with a definitive list of structures to search to see if containers got created in them
- that point to the structure being torn down.
-*/
+ * that are pointed to by any container vars in any of the passed through vars and any of the vars those point to, etc.
+ * The objective is to come up with a definitive list of structures to search to see if containers got created in them
+ * that point to the structure being torn down.
+ */
typedef struct lv_xnewref_struct
{
struct lv_xnewref_struct *next;
@@ -328,21 +350,22 @@ typedef struct symval_struct
int4 symvlvl; /* Level of symval struct (nesting) */
boolean_t trigr_symval; /* Symval is owned by a trigger */
boolean_t alias_activity;
+ GTM64_ONLY(int4 filler;)
} symval;
/* Structure to describe the block allocated to describe a var specified on a TSTART to be restored
- on a TP restart. Block moved here from tpframe.h due to the structure references it [now] makes.
- Block can take two forms: (1) the standard tp_data form which marks vars to be modified or (2) the
- tp_change form where a new symbol table was stacked.
-*/
+ * on a TP restart. Block moved here from tpframe.h due to the structure references it [now] makes.
+ * Block can take two forms: (1) the standard tp_data form which marks vars to be modified or (2) the
+ * tp_change form where a new symbol table was stacked.
+ */
typedef struct tp_var_struct
{
- struct tp_var_struct *next;
- struct lv_val_struct *current_value;
- struct lv_val_struct *save_value;
- mname_entry key;
- boolean_t var_cloned;
- GTM64_ONLY(int4 filler;)
+ struct tp_var_struct *next;
+ struct lv_val_struct *current_value;
+ struct lv_val_struct *save_value;
+ mname_entry key;
+ boolean_t var_cloned;
+ GTM64_ONLY(int4 filler;)
} tp_var;
typedef struct lvname_info_struct
@@ -354,6 +377,81 @@ typedef struct lvname_info_struct
} lvname_info;
typedef lvname_info *lvname_info_ptr;
+#define ASSERT_ACTIVELV_GOOD(LV) assert((NULL == LV) || (NULL == LV_AVLNODE_PARENT(LV)) \
+ || LV_IS_VAL_DEFINED(LV) || LV_HAS_CHILD(LV));
+
+/* Although the below typedef is used only in DBG, define it for PRO too as gtmpcat requires this */
+typedef struct activelv_dbg_struct
+{
+ lv_val *active_lv;
+ lv_val *newlv;
+ struct stack_frame_struct *frame_pointer;
+ symval *curr_symval;
+ unsigned char *mpc;
+ unsigned char *ctxt;
+ uint4 count;
+ uint4 type;
+} activelv_dbg_t;
+
+enum actlv_type
+{
+ actlv_op_putindx1 = 1, /* = 1 */
+ actlv_op_putindx2, /* = 2 */
+ actlv_lv_kill, /* = 3 */
+ actlv_op_zshow, /* = 4 */
+ actlv_op_killalias, /* = 5 */
+ actlv_op_killaliasall, /* = 6 */
+ actlv_op_setals2als, /* = 7 */
+ actlv_op_setalsctin2als, /* = 8 */
+ actlv_op_setfnretin2als, /* = 9 */
+ actlv_op_xkill, /* = 10 */
+ actlv_unw_mv_ent, /* = 11 */
+ actlv_op_tstart, /* = 12 */
+ actlv_gtm_fetch, /* = 13 */
+ actlv_mdb_condition_handler, /* = 14 */
+ actlv_merge_desc_check1, /* = 15 */
+ actlv_merge_desc_check2, /* = 16 */
+ actlv_merge_desc_check3, /* = 17 */
+ actlv_op_merge1, /* = 18 */
+ actlv_op_merge2, /* = 19 */
+ actlv_tp_unwind_restart, /* = 20 */
+ actlv_tp_unwind_rollback, /* = 21 */
+ actlv_tp_unwind_commit /* = 22 */
+};
+
+#ifdef DEBUG
+void set_active_lv(lv_val *newlv, boolean_t do_assert, int type);
+
+# define SET_ACTIVE_LV(NEWLV, DO_ASSERT, TYPE) set_active_lv((lv_val *)NEWLV, DO_ASSERT, TYPE)
+#else
+# define SET_ACTIVE_LV(NEWLV, DO_ASSERT, TYPE) \
+{ \
+ GBLREF lv_val *active_lv; \
+ \
+ active_lv = (lv_val *)NEWLV; \
+}
+#endif
+
+#define UNDO_ACTIVE_LV(ACTIVELV_CODE) \
+{ \
+ GBLREF lv_val *active_lv; \
+ \
+ if (NULL != active_lv) \
+ { /* If LV_AVLNODE_PARENT is NULL, it means the node has already been \
+ * freed. We dont know of any such case right now so assert. In PRO \
+ * though we want to be safe so we skip the kill in that case but \
+ * reset active_lv to NULL. \
+ */ \
+ assert(NULL != LV_AVLNODE_PARENT(active_lv)); \
+ if (NULL != LV_AVLNODE_PARENT(active_lv)) \
+ { \
+ if (!LV_IS_VAL_DEFINED(active_lv) && !LV_HAS_CHILD(active_lv)) \
+ op_kill(active_lv); \
+ } \
+ SET_ACTIVE_LV(NULL, FALSE, ACTIVELV_CODE); \
+ } \
+}
+
#define DOTPSAVE_FALSE FALSE /* macro to indicate parameter by name "dotpsave" is passed a value of "FALSE" */
#define DOTPSAVE_TRUE TRUE /* macro to indicate parameter by name "dotpsave" is passed a value of "TRUE" */
@@ -377,7 +475,7 @@ typedef lvname_info *lvname_info_ptr;
assert(NULL != LVT_GET_PARENT(LVT)); \
LVT_PARENT(LVT) = NULL; /* indicates this is free */ \
/* avl_root is overloaded to store linked list in free state */ \
- LVT->avl_root = (lvTreeNode *)sym->lvtree_flist; \
+ LVT->avl_root = (lvTreeNode *)sym->lvtree_flist; \
sym->lvtree_flist = LVT; \
}
@@ -406,7 +504,7 @@ void lv_newblock(symval *sym, int numElems);
void lv_newname(ht_ent_mname *hte, symval *sym);
void lvtree_newblock(symval *sym, int numElems);
void lvtreenode_newblock(symval *sym, int numElems);
-void lv_var_clone(lv_val *clone_var, lv_val *base_lv);
+void lv_var_clone(lv_val *clone_var, lv_val *base_lv, boolean_t refCntMaint);
void lvzwr_var(lv_val *lv, int4 n);
void op_clralsvars(lv_val *dst);
diff --git a/sr_port/lv_var_clone.c b/sr_port/lv_var_clone.c
index 58741ba..4ac07fd 100644
--- a/sr_port/lv_var_clone.c
+++ b/sr_port/lv_var_clone.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,6 +16,7 @@
#include "gtm_string.h"
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "gdsroot.h"
#include "gtm_facility.h"
@@ -30,9 +31,12 @@
* xnew processing where we are cloneing a tree out of one symtab and into another. The new tree will be
* created in the symtab of the input lv_val regardless of which symtab owns the processed lv_vals.
*
- * Input "base_lv" is the base variable that the cloned tree should point back to.
+ * Inputs:
+ * - clone_var is the base variable that we are cloning into.
+ * - base_lv is the base variable that the cloned tree should point back to.
+ * - refCntMaint is whether we should bump refcnts for the targets of any alias containers we locate.
*/
-void lv_var_clone(lv_val *clone_var, lv_val *base_lv)
+void lv_var_clone(lv_val *clone_var, lv_val *base_lv, boolean_t refCntMaint)
{
lvTree *clone_lvt;
@@ -40,11 +44,12 @@ void lv_var_clone(lv_val *clone_var, lv_val *base_lv)
assert(LV_IS_BASE_VAR(clone_var));
assert(base_lv);
assert(LV_IS_BASE_VAR(base_lv));
- DBGRFCT((stderr, "\nlv_var_clone: Cloning lv_val tree at 0x"lvaddr"\n", clone_var));
+ DBGRFCT((stderr, "\nlv_var_clone: Cloning base lv_val tree at 0x"lvaddr" into save_lv 0x"lvaddr"\n", base_lv, clone_var));
clone_lvt = LV_GET_CHILD(clone_var); /* "clone_lvt" holds tree to be cloned as we build new tree for clone_var */
if (NULL != clone_lvt)
{
assert(1 == clone_lvt->sbs_depth);
- LV_TREE_CLONE(clone_lvt, (lvTreeNode *)clone_var, base_lv);
+ LV_TREE_CLONE(clone_lvt, (lvTreeNode *)clone_var, base_lv, refCntMaint);
}
+ DBGRFCT((stderr, "lv_var_clone: Cloning of base lv_val tree at 0x"lvaddr" complete\n\n", base_lv));
}
diff --git a/sr_port/lvzwr_fini.c b/sr_port/lvzwr_fini.c
index 3282545..be9d41c 100644
--- a/sr_port/lvzwr_fini.c
+++ b/sr_port/lvzwr_fini.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -29,6 +29,7 @@
GBLREF symval *curr_symval;
GBLREF lvzwrite_datablk *lvzwrite_block;
+GBLREF bool undef_inhibit;
GBLREF zshow_out *zwr_output;
error_def(ERR_UNDEF);
@@ -52,7 +53,8 @@ void lvzwr_fini(zshow_out *out, int t)
if (!tabent || !LV_IS_VAL_DEFINED(tabent->value) && !LV_HAS_CHILD(tabent->value))
{
lvzwrite_block->subsc_count = 0;
- rts_error(VARLSTCNT(4) ERR_UNDEF, 2, size, lvzwrite_block->pat->str.addr);
+ if (!undef_inhibit)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_UNDEF, 2, size, lvzwrite_block->pat->str.addr);
} else
{
lvzwrite_block->curr_name = &tabent->key.var_name;
diff --git a/sr_port/lvzwr_out.c b/sr_port/lvzwr_out.c
index 538798c..ae1d578 100644
--- a/sr_port/lvzwr_out.c
+++ b/sr_port/lvzwr_out.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_string.h"
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "gdsroot.h"
#include "gdskill.h"
@@ -43,6 +44,8 @@
#include "callg.h"
#include "gtmimagename.h"
#include "format_targ_key.h" /* for ISSUE_GVSUBOFLOW_ERROR macro */
+#include <rtnhdr.h>
+#include "stack_frame.h"
GBLREF lvzwrite_datablk *lvzwrite_block;
GBLREF zshow_out *zwr_output;
@@ -324,7 +327,7 @@ void lvzwr_out(lv_val *lvp)
param_list.n = n + 1;
dst_lv = (lv_val *)callg((callgfnptr)op_putindx, ¶m_list);
MV_FORCE_STR(val);
- DECR_AC_REF(dst_lv, TRUE);
+ assert(!(MV_ALIASCONT & dst_lv->v.mvtype)); /* op_putindx would have already done DECR_AC_REF for us */
dst_lv->v = *val;
dst_lv->v.mvtype &= ~MV_ALIASCONT; /* Make sure alias container property does not pass */
}
diff --git a/sr_port/lvzwr_var.c b/sr_port/lvzwr_var.c
index 6ac4019..e5e7e60 100644
--- a/sr_port/lvzwr_var.c
+++ b/sr_port/lvzwr_var.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -124,6 +124,7 @@ GBLREF lvzwrite_datablk *lvzwrite_block;
GBLREF int4 outofband;
GBLREF zshow_out *zwr_output;
GBLREF int merge_args;
+GBLREF bool undef_inhibit;
GBLREF zwr_hash_table *zwrhtab; /* How we track aliases during zwrites */
LITREF mval literal_null;
@@ -177,8 +178,11 @@ void lvzwr_var(lv_val *lv, int4 n)
return;
if (outofband)
{
+ assert(TREF(in_zwrite));
+ TREF(in_zwrite) = FALSE;
lvzwrite_block->curr_subsc = lvzwrite_block->subsc_count = 0;
outofband_action(FALSE);
+ TREF(in_zwrite) = TRUE;
}
lvzwrite_block->curr_subsc = n;
zwr_sub = (zwr_sub_lst *)lvzwrite_block->sub;
@@ -270,7 +274,8 @@ void lvzwr_var(lv_val *lv, int4 n)
end = lvzwr_key(buff, SIZEOF(buff));
zwr_sub->subsc_list[n].actual = (mval *)NULL;
lvzwrite_block->curr_subsc = lvzwrite_block->subsc_count = 0;
- rts_error(VARLSTCNT(4) ERR_UNDEF, 2, end - buff, buff);
+ if (!undef_inhibit)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_UNDEF, 2, end - buff, buff);
}
}
} else if (lvt = LV_GET_CHILD(lv))
diff --git a/sr_port/m_break.c b/sr_port/m_break.c
index c59bf66..8aa73ef 100644
--- a/sr_port/m_break.c
+++ b/sr_port/m_break.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Inforformation Services, Inc *
+ * Copyright 2001, 2014 Fidelity Inforformation Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,9 +24,7 @@ int m_break(void)
if (!m_xecute())
return FALSE;
newtriple(OC_BREAK);
- if (TREF(for_stack_ptr) == TADR(for_stack))
- start_fetches (OC_FETCH);
- else
- start_for_fetches ();
+ /* Because the activity in direct mode brought on by the BREAK can alter the environment, start a new fetch */
+ MID_LINE_REFETCH;
return TRUE;
}
diff --git a/sr_port/m_do.c b/sr_port/m_do.c
index baf4491..57d17ac 100644
--- a/sr_port/m_do.c
+++ b/sr_port/m_do.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -70,7 +70,7 @@ int m_do(void)
assert(TRIP_REF == calltrip->operand[1].oprclass);
if (OC_CDLIT == calltrip->operand[1].oprval.tref->opcode)
assert(CDLT_REF == calltrip->operand[1].oprval.tref->operand[0].oprclass);
- else
+ else USHBIN_ONLY(if (OC_LAB_EXT != calltrip->operand[1].oprval.tref->opcode))
{
assert(OC_LABADDR == calltrip->operand[1].oprval.tref->opcode);
assert(TRIP_REF == calltrip->operand[1].oprval.tref->operand[1].oprclass);
diff --git a/sr_port/m_new.c b/sr_port/m_new.c
index fa413d8..510db3b 100644
--- a/sr_port/m_new.c
+++ b/sr_port/m_new.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,12 +22,12 @@
#include "cmd.h"
#include "namelook.h"
-GBLREF triple *curr_fetch_trip, *curr_fetch_opr;
GBLREF int4 curr_fetch_count;
+GBLREF triple *curr_fetch_opr, *curr_fetch_trip;
-LITREF unsigned char svn_index[];
LITREF nametabent svn_names[];
LITREF svn_data_type svn_data[];
+LITREF unsigned char svn_index[];
error_def(ERR_INVSVN);
error_def(ERR_RPARENMISSING);
@@ -37,12 +37,11 @@ error_def(ERR_VAREXPECTED);
int m_new(void)
{
- oprtype tmparg;
- triple *ref, *next, *org, *tmp, *s, *fetch;
- int n;
- int count;
- mvar *var;
boolean_t parse_warn;
+ int count, n;
+ mvar *var;
+ oprtype tmparg;
+ triple *fetch, *next, *org, *ref, *s, *tmp;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -113,13 +112,12 @@ int m_new(void)
return FALSE;
case TK_EOL:
case TK_SPACE:
+ /* This actually a NEW all, but an XNEW with no arguments does the job */
tmp = maketriple(OC_XNEW);
tmp->operand[0] = put_ilit((mint) 0);
ins_triple(tmp);
- if (TREF(for_stack_ptr) == TADR(for_stack))
- start_fetches (OC_FETCH);
- else
- start_for_fetches ();
+ /* start a new fetch for whatever follows on the line */
+ MID_LINE_REFETCH;
return TRUE;
case TK_LPAREN:
ref = org = maketriple(OC_XNEW);
@@ -158,10 +156,8 @@ int m_new(void)
advancewindow();
org->operand[0] = put_ilit((mint) count);
ins_triple(org);
- if (TREF(for_stack_ptr) == TADR(for_stack))
- start_fetches (OC_FETCH);
- else
- start_for_fetches ();
+ /* start a new fetch for whatever follows on the line */
+ MID_LINE_REFETCH;
return TRUE;
default:
stx_error(ERR_VAREXPECTED);
diff --git a/sr_port/m_zhalt.c b/sr_port/m_zhalt.c
index d9f1b8d..4cae1fc 100644
--- a/sr_port/m_zhalt.c
+++ b/sr_port/m_zhalt.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2011 Fidelity Information Services, Inc *
+ * Copyright 2011, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,10 +11,10 @@
#include "mdef.h"
-#include "cmd.h"
#include "compiler.h"
#include "indir_enum.h"
#include "opcode.h"
+#include "cmd.h"
#include "toktyp.h"
LITREF mval literal_zero;
@@ -35,17 +35,17 @@ int m_zhalt(void)
return m_halt();
switch (status = expr(&ot, MUMPS_NUM)) /* NOTE assignment */
{
- case EXPR_FAIL:
- return FALSE;
- case EXPR_GOOD:
- triptr = newtriple(OC_ZHALT);
- triptr->operand[0] = ot;
- return TRUE;
- case EXPR_INDR:
- make_commarg(&ot, indir_zhalt);
- return TRUE;
- default:
- GTMASSERT;
+ case EXPR_FAIL:
+ return FALSE;
+ case EXPR_GOOD:
+ triptr = newtriple(OC_ZHALT);
+ triptr->operand[0] = ot;
+ return TRUE;
+ case EXPR_INDR:
+ make_commarg(&ot, indir_zhalt);
+ return TRUE;
+ default:
+ assertpro(FALSE);
}
return FALSE; /* This should never get executed, added to make compiler happy */
}
diff --git a/sr_port/md5_digest2hex.c b/sr_port/md5_digest2hex.c
new file mode 100644
index 0000000..40c8939
--- /dev/null
+++ b/sr_port/md5_digest2hex.c
@@ -0,0 +1,40 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include "copy.h"
+#include "eintr_wrappers.h"
+#include "gtm_string.h"
+#include "io.h"
+#include "gtmio.h"
+
+#include "md5hash.h"
+#include "md5_digest2hex.h"
+
+/*
+ * Construct printable 32-character MD5 checksum string from raw 128-bit digest array.
+ */
+void md5_digest2hex(char hexstr[MD5_HEXSTR_LENGTH], const unsigned char digest[MD5_DIGEST_LENGTH])
+{
+ int i, tlen;
+ char *bptr;
+
+ bptr = (char *)&hexstr[0];
+ /* TODO - improve efficiency to avoid syscall using i2hexl() */
+ for (i = 0; i < MD5_DIGEST_LENGTH; i++)
+ {
+ tlen = SPRINTF(bptr, "%02x", digest[i]);
+ assert(2 == tlen);
+ bptr += tlen;
+ }
+ assert('\0' == hexstr[MD5_HEXSTR_LENGTH - 1]);
+}
diff --git a/sr_port/dse_is_blk_free.h b/sr_port/md5_digest2hex.h
similarity index 56%
copy from sr_port/dse_is_blk_free.h
copy to sr_port/md5_digest2hex.h
index 23b7777..fe3322c 100644
--- a/sr_port/dse_is_blk_free.h
+++ b/sr_port/md5_digest2hex.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,12 +9,13 @@
* *
****************************************************************/
-#ifndef DSE_IS_BLK_FREE_DEFINED
+#ifndef MD5_DIGEST2HEX_INCLUDED
+#define MD5_DIGEST2HEX_INCLUDED
-/* Declare parms for dse_is_blk_free.c */
+#include "md5hash.h"
-bool dse_is_blk_free (block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr);
+#define MD5_HEXSTR_LENGTH 33
-#define DSE_IS_BLK_FREE_DEFINED
+void md5_digest2hex(char hexstr[MD5_HEXSTR_LENGTH], const unsigned char digest[MD5_DIGEST_LENGTH]);
-#endif
+#endif /* MD5_DIGEST2HEX_INCLUDED */
diff --git a/sr_port/mdb_condition_handler.c b/sr_port/mdb_condition_handler.c
index eed2f1e..30f8d6e 100644
--- a/sr_port/mdb_condition_handler.c
+++ b/sr_port/mdb_condition_handler.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -15,6 +15,7 @@
#include "gtm_stdlib.h"
#include "gtm_inet.h" /* Required for gtmsource.h */
#include "gtm_stdio.h"
+#include "gtm_fcntl.h" /* Needed for AIX's silly open to open64 translations */
#ifdef VMS
# include <descrip.h> /* required for gtmsource.h */
@@ -35,6 +36,7 @@
#include "gdscc.h"
#include "gdskill.h"
#include "gt_timer.h"
+#include "gtmio.h"
#include "filestruct.h"
#include "gtmdbglvl.h"
#include "error.h"
@@ -90,67 +92,51 @@
# include "gtm_trigger.h"
#endif
-GBLREF spdesc stringpool, rts_stringpool, indr_stringpool;
-GBLREF volatile int4 outofband;
-GBLREF volatile bool std_dev_outbnd;
-GBLREF unsigned char *restart_pc;
-GBLREF unsigned char *restart_ctxt;
-GBLREF unsigned char *stackwarn, *tpstackwarn;
-GBLREF unsigned char *stacktop, *tpstacktop;
-GBLREF unsigned char *msp, *tp_sp;
-GBLREF mv_stent *mv_chain;
-GBLREF stack_frame *frame_pointer, *zyerr_frame, *error_frame;
-GBLREF tp_frame *tp_pointer;
-GBLREF io_desc *active_device;
-GBLREF lv_val *active_lv;
-GBLREF io_pair io_std_device, io_curr_device;
-GBLREF mval dollar_ztrap;
-GBLREF volatile bool neterr_pending;
-GBLREF xfer_entry_t xfer_table[];
-GBLREF unsigned short proc_act_type;
-GBLREF int mumps_status;
-GBLREF mstr *err_act;
-GBLREF tp_region *tp_reg_list; /* Chained list of regions used in this transaction not cleared on tp_restart */
-GBLREF uint4 gtmDebugLevel; /* Debug level */
-GBLREF uint4 process_id;
-GBLREF jnlpool_addrs jnlpool;
-GBLREF boolean_t pool_init;
-GBLREF boolean_t created_core;
-GBLREF boolean_t dont_want_core;
-GBLREF mval dollar_zstatus, dollar_zerror;
-GBLREF mval dollar_etrap;
-GBLREF volatile int4 gtmMallocDepth;
-GBLREF int4 exi_condition;
-GBLREF inctn_opcode_t inctn_opcode;
-#ifdef VMS
-GBLREF struct chf$signal_array *tp_restart_fail_sig;
-GBLREF boolean_t tp_restart_fail_sig_used;
-#endif
-GBLREF int merge_args;
-GBLREF lvzwrite_datablk *lvzwrite_block;
-GBLREF volatile boolean_t dollar_zininterrupt;
+GBLREF boolean_t ctrlc_on, created_core, dont_want_core, in_gvcst_incr, pool_init;
GBLREF boolean_t ztrap_explicit_null; /* whether $ZTRAP was explicitly set to NULL in this frame */
GBLREF dollar_ecode_type dollar_ecode; /* structure containing $ECODE related information */
-GBLREF boolean_t in_gvcst_incr;
-GBLREF gv_namehead *gv_target;
+GBLREF dollar_stack_type dollar_stack;
GBLREF gd_region *gv_cur_region;
GBLREF gv_key *gv_currkey;
+GBLREF gv_namehead *gv_target;
+GBLREF inctn_opcode_t inctn_opcode;
+GBLREF int mumps_status, merge_args;
+GBLREF int4 exi_condition;
+GBLREF io_desc *active_device, *gtm_err_dev;
+GBLREF io_pair io_std_device, io_curr_device;
+GBLREF jnlpool_addrs jnlpool;
+GBLREF lvzwrite_datablk *lvzwrite_block;
+GBLREF mstr *err_act;
+GBLREF mval *alias_retarg, dollar_etrap, dollar_zstatus, dollar_zerror, dollar_ztrap;
+GBLREF mv_stent *mv_chain;
+GBLREF sgm_info *first_sgm_info;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF sgm_info *first_sgm_info;
-GBLREF dollar_stack_type dollar_stack;
-GBLREF mval *alias_retarg;
-#ifdef UNIX
-GBLREF jnl_gbls_t jgbl;
+GBLREF spdesc indr_stringpool, rts_stringpool, stringpool;
+GBLREF stack_frame *frame_pointer, *zyerr_frame, *error_frame;
+GBLREF tp_frame *tp_pointer;
+GBLREF tp_region *tp_reg_list; /* Chained list of regions in this transaction not cleared on tp_restart */
+GBLREF uint4 gtmDebugLevel; /* Debug level */
+GBLREF uint4 process_id;
+GBLREF unsigned char *msp, *restart_ctxt, *restart_pc, *stacktop, *stackwarn, *tp_sp, *tpstacktop, *tpstackwarn;
+GBLREF unsigned short proc_act_type;
+GBLREF volatile bool neterr_pending, std_dev_outbnd;
+GBLREF volatile boolean_t dollar_zininterrupt;
+GBLREF volatile int4 gtmMallocDepth, outofband;
+GBLREF xfer_entry_t xfer_table[];
+#ifdef DEBUG
+GBLREF boolean_t donot_INVOKE_MUMTSTART;
#endif
-GBLREF io_desc *gtm_err_dev;
#ifdef GTM_TRIGGER
-GBLREF int tprestart_state; /* When triggers restart, multiple states possible.
- See tp_restart.h */
+GBLREF int tprestart_state; /* When triggers restart, multiple states possible - see tp_restart.h */
GBLREF int4 gtm_trigger_depth;
#endif
-#ifdef DEBUG
-GBLREF boolean_t donot_INVOKE_MUMTSTART;
+#ifdef UNIX
+GBLREF jnl_gbls_t jgbl;
+#endif
+#ifdef VMS
+GBLREF boolean_t tp_restart_fail_sig_used;
+GBLREF struct chf$signal_array *tp_restart_fail_sig;
#endif
error_def(ERR_ASSERT);
@@ -208,6 +194,26 @@ void setup_error(sgmnt_addrs *csa, int argcnt, ...);
#define MUM_TSTART_FRAME_CHECK
#endif
+/* Since a call to SET_ZSTATUS may cause the stringpool expansion, record whether we are using an indirection pool or not
+ * in a local variable rather than recompare the stringpool bases.
+ */
+#define SAVE_ZSTATUS_INTO_RTS_STRINGPOOL(VAR, ARG) \
+{ \
+ boolean_t using_indrpool; \
+ \
+ using_indrpool = (stringpool.base != rts_stringpool.base); \
+ if (using_indrpool) \
+ { \
+ indr_stringpool = stringpool; /* update indr_stringpool */ \
+ stringpool = rts_stringpool; /* change for set_zstatus */ \
+ } \
+ VAR = SET_ZSTATUS(ARG); \
+ if (using_indrpool) \
+ { \
+ rts_stringpool = stringpool; /* update rts_stringpool */ \
+ stringpool = indr_stringpool; /* change back */ \
+ } \
+}
/* We ignore errors in the $ZYERROR routine. When an error occurs, we unwind all stack frames upto and including
* zyerr_frame. MUM_TSTART then transfers control to the $ZTRAP frame.
@@ -251,7 +257,7 @@ void setup_error(sgmnt_addrs *csa, int argcnt, ...)
CONDITION_HANDLER(mdb_condition_handler)
{
- unsigned char *cp, *context, *sp_base;
+ unsigned char *cp, *context;
boolean_t dm_action; /* did the error occur on a action from direct mode */
boolean_t trans_action; /* did the error occur during "transcendental" code */
char src_line[MAX_ENTRYREF_LEN];
@@ -265,7 +271,6 @@ CONDITION_HANDLER(mdb_condition_handler)
boolean_t error_in_zyerror;
boolean_t repeat_error, etrap_handling, reset_mpc;
int level, rc;
- lv_val *lvptr;
boolean_t reserve_sock_dev = FALSE;
# ifdef UNIX
unix_db_info *udi;
@@ -293,22 +298,9 @@ CONDITION_HANDLER(mdb_condition_handler)
if (repeat_error = (ERR_REPEATERROR == SIGNAL)) /* assignment and comparison */
SIGNAL = dollar_ecode.error_last_ecode;
preemptive_db_clnup(SEVERITY);
+ assert(NULL == alias_retarg);
if (NULL != alias_retarg)
- { /* An error has occurred while an alias return arg was in-flight. Delivery won't happen now
- * so we need to remove the extra counts that were added in unw_retarg() and dis-enchant
- * the alias container itself.
- */
- assert(alias_retarg->mvtype & MV_ALIASCONT);
- if (alias_retarg->mvtype & MV_ALIASCONT)
- { /* Protect the refs were are about to make in case ptr got banged up somehow */
- lvptr = (lv_val *)alias_retarg->str.addr;
- assert(LV_IS_BASE_VAR(lvptr));
- DECR_CREFCNT(lvptr);
- DECR_TREFCNT(lvptr);
- }
- alias_retarg->mvtype = 0; /* Kill the temp var (no longer a container) */
- alias_retarg = NULL; /* .. and no more in-flight return argument */
- }
+ CLEAR_ALIAS_RETARG;
if ((int)ERR_UNSOLCNTERR == SIGNAL)
{
/* This is here for linking purposes. We want to delay the receipt of
@@ -386,6 +378,17 @@ CONDITION_HANDLER(mdb_condition_handler)
assertpro((SFT_TRIGR & frame_pointer->type) && (0 < gtm_trigger_depth));
mumps_status = rc;
DBGEHND((stderr, "mdb_condition_handler: Unwind-return to caller (gtm_trigger)\n"));
+ /* It is possible that dollar_tlevel at the time of the ESTABLISH of mdb_condition_handler
+ * was higher than the current dollar_tlevel. This is because tp_restart done above could
+ * have decreased dollar_tlevel. Even though dollar_tlevel before the UNWIND done
+ * below is not the same as that at ESTABLISH_RET time, the flow of control bubbles back
+ * correctly to the op_tstart at $tlevel=1 and resumes execution. So treat this as an exception
+ * and adjust active_ch->dollar_tlevel so it is in sync with the current dollar_tlevel. This
+ * prevents an assert failure in UNWIND. START_CH would have done a active_ch-- So we need a
+ * active_ch[1] to get at the desired active_ch. See similar code in tp_restart.c.
+ */
+ UNIX_ONLY(assert(active_ch[1].dollar_tlevel >= dollar_tlevel);)
+ UNIX_ONLY(DEBUG_ONLY(active_ch[1].dollar_tlevel = dollar_tlevel;))
UNWIND(NULL, NULL);
}
/* "tp_restart" has succeeded so we have unwound back to the return point but check if the
@@ -554,12 +557,7 @@ CONDITION_HANDLER(mdb_condition_handler)
# ifdef GTM_TRIGGER
assertpro(TPRESTART_STATE_NORMAL == tprestart_state); /* Can't leave half-restarted transaction around - out of design */
# endif
- if (active_lv)
- {
- if (!LV_IS_VAL_DEFINED(active_lv) && !LV_HAS_CHILD(active_lv))
- op_kill(active_lv);
- active_lv = (lv_val *)0;
- }
+ UNDO_ACTIVE_LV(actlv_mdb_condition_handler);
/*
* If error is at least severity "WARNING", do some cleanups. Note: crit is no longer unconditionally
* released here. It is now released if NOT in TP (any retry) or if in TP but NOT in the final retry.
@@ -727,22 +725,11 @@ CONDITION_HANDLER(mdb_condition_handler)
if (!repeat_error)
/* This has already been done if we are re-throwing the error */
outofband_clear();
- if (!trans_action && !dm_action && !(frame_pointer->type & SFT_DM))
+ if (!trans_action && !ctrlc_on && !(frame_pointer->type & SFT_DM))
{
- sp_base = stringpool.base;
- if (sp_base != rts_stringpool.base)
- {
- indr_stringpool = stringpool; /* update indr_stringpool */
- stringpool = rts_stringpool; /* change for set_zstatus */
- }
if (!repeat_error)
{
- dollar_ecode.error_last_b_line = SET_ZSTATUS(NULL);
- }
- if (sp_base != rts_stringpool.base)
- {
- rts_stringpool = stringpool; /* update rts_stringpool */
- stringpool = indr_stringpool; /* change back */
+ SAVE_ZSTATUS_INTO_RTS_STRINGPOOL(dollar_ecode.error_last_b_line, NULL);
}
assert(NULL != dollar_ecode.error_last_b_line);
/* Only (re)set restart_pc if we are in the original frame. This is needed to restart execution at the
@@ -893,27 +880,20 @@ CONDITION_HANDLER(mdb_condition_handler)
*/
if (!dm_action)
{
- sp_base = stringpool.base;
- if (sp_base != rts_stringpool.base)
- {
- indr_stringpool = stringpool; /* update indr_stringpool */
- stringpool = rts_stringpool; /* change for set_zstatus */
- }
if (!repeat_error)
- dollar_ecode.error_last_b_line = SET_ZSTATUS(&context);
- assert(NULL != dollar_ecode.error_last_b_line);
- if (sp_base != rts_stringpool.base)
{
- rts_stringpool = stringpool; /* update rts_stringpool */
- stringpool = indr_stringpool; /* change back */
+ SAVE_ZSTATUS_INTO_RTS_STRINGPOOL(dollar_ecode.error_last_b_line, &context);
}
+ assert(NULL != dollar_ecode.error_last_b_line);
}
if ((SUCCESS == SEVERITY) || (INFO == SEVERITY))
{
- /* skip printing error messages for INFO messages if this variable is set.
+ /* In VMS skip printing error messages for INFO messages if skip_gtm_putmsg is TRUE.
* this is currently relied upon by GDE for the VIEW "YCHKCOLL" command.
+ * In UNIX send out messages only in utilities or direct mode, this addresses the GDE
+ * issue described above for VMS as GDE is never in direct mode
*/
- if (!TREF(skip_gtm_putmsg))
+ if (UNIX_ONLY(!IS_GTM_IMAGE || dm_action) VMS_ONLY(!TREF(skip_gtm_putmsg)))
PRN_ERROR;
CONTINUE;
}
diff --git a/sr_port/mdef.h b/sr_port/mdef.h
index 5affbc8..bb3946a 100644
--- a/sr_port/mdef.h
+++ b/sr_port/mdef.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -610,6 +610,7 @@ int gtm_assert2(int condlen, char *condtext, int file_name_len, char file_name[]
#define DBG_MARK_RTS_ERROR_USABLE
#define DBG_MARK_RTS_ERROR_UNUSABLE
#endif
+
int rts_error(int argcnt, ...);
int rts_error_csa(void *csa, int argcnt, ...); /* Use CSA_ARG(CSA) for portability */
#define CSA_ARG(CSA) (CSA),
@@ -628,10 +629,11 @@ int4 timeout2msec(int4 timeout);
/* the RTS_ERROR_TEXT macro will stay till all existing references to it have been renamed to RTS_ERROR_{LITERAL,STRING} */
#define RTS_ERROR_TEXT(STRING) LENGTH_AND_STRING(STRING)
-
/* for those who prefer not remembering the order of the length and the literal/string in the rts_error command line */
#define RTS_ERROR_LITERAL(LITERAL) LENGTH_AND_LITERAL(LITERAL)
#define RTS_ERROR_STRING(STRING) LENGTH_AND_STRING(STRING)
+#define RTS_ERROR_MSTR(MSTR) (MSTR)->len, (MSTR)->addr
+#define RTS_ERROR_MVAL(MVAL) RTS_ERROR_MSTR(&(MVAL)->str)
#define SET_PROCESS_EXITING_TRUE \
{ \
diff --git a/sr_port/merge_desc_check.c b/sr_port/merge_desc_check.c
index d06e44a..fa47155 100644
--- a/sr_port/merge_desc_check.c
+++ b/sr_port/merge_desc_check.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,6 +33,7 @@
#include "op_merge.h"
#include "format_targ_key.h"
#include "ddphdr.h"
+#include "mvalconv.h"
GBLREF int merge_args;
GBLREF merge_glvn_ptr mglvnp;
@@ -45,17 +46,19 @@ error_def(ERR_MERGEDESC);
*/
boolean_t merge_desc_check(void)
{
- boolean_t mergereg_array[256], *is_reg_in_array, intersect;
+ boolean_t intersect, *is_reg_in_array, mergereg_array[256];
char *base;
enum db_acc_method acc_meth1, acc_meth2;
gd_addr *addr;
- gd_binding *map, *start_map1, *end_map1, *start_map2, *end_map2;
+ gd_binding *end_map1, *end_map2, *map, *start_map1, *start_map2;
gd_region *reg, *reg1, *reg2;
gv_key *gvkey1, *gvkey2;
gv_namehead *gvt1, *gvt2;
gvname_info *gblp1, *gblp2;
gvnh_reg_t *gvnh_reg1, *gvnh_reg2;
- int max_fid_index;
+ int dollardata_src, max_fid_index;
+ lv_val *dst, *src;
+ mval tmp_mval;
sgmnt_addrs *csa;
unsigned char buff1[MAX_ZWR_KEY_SZ], buff2[MAX_ZWR_KEY_SZ], *end1, *end2;
DCL_THREADGBL_ACCESS;
@@ -218,19 +221,41 @@ boolean_t merge_desc_check(void)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_MERGEDESC, 4, end2 - buff2, buff2, end1 - buff1, buff1);
} else if (MARG1_IS_LCL(merge_args) && MARG2_IS_LCL(merge_args))
{
- if (mglvnp->lclp[IND1] == mglvnp->lclp[IND2])
- return 0; /* NOOP - merge self */
- if (lcl_arg1_is_desc_of_arg2(mglvnp->lclp[IND1], mglvnp->lclp[IND2]))
+ dst = mglvnp->lclp[IND1];
+ src = mglvnp->lclp[IND2];
+ if ((dst == src) || (NULL == src))
+ { /* NOOP - merge self OR empty subscripted source */
+ UNDO_ACTIVE_LV(actlv_merge_desc_check1); /* kill "dst" and parents as applicable if $data(dst)=0 */
+ return 0;
+ }
+ if (lcl_arg1_is_desc_of_arg2(dst, src))
{
- end1 = format_key_lv_val(mglvnp->lclp[IND1], buff1, SIZEOF(buff1));
- end2 = format_key_lv_val(mglvnp->lclp[IND2], buff2, SIZEOF(buff2));
+ end1 = format_key_lv_val(dst, buff1, SIZEOF(buff1));
+ UNDO_ACTIVE_LV(actlv_merge_desc_check2); /* kill "dst" and parents as applicable if $data(dst)=0 */
+ op_fndata(src, &tmp_mval);
+ dollardata_src = MV_FORCE_INTD(&tmp_mval);
+ if (0 == dollardata_src)
+ return 0; /* NOOP - merge x(subs)=x, but x is undefined */
+ end2 = format_key_lv_val(src, buff2, SIZEOF(buff2));
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_MERGEDESC, 4, end1 - buff1, buff1, end2 - buff2, buff2);
- } else if (lcl_arg1_is_desc_of_arg2(mglvnp->lclp[IND2], mglvnp->lclp[IND1]))
+ }
+ if (lcl_arg1_is_desc_of_arg2(src, dst))
{
- end1 = format_key_lv_val(mglvnp->lclp[IND1], buff1, SIZEOF(buff1));
- end2 = format_key_lv_val(mglvnp->lclp[IND2], buff2, SIZEOF(buff2));
+ /* No need of UNDO_ACTIVE_LV since src is a descendant of dst and so $data(dst) is != 0 */
+ end1 = format_key_lv_val(dst, buff1, SIZEOF(buff1));
+ end2 = format_key_lv_val(src, buff2, SIZEOF(buff2));
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_MERGEDESC, 4, end2 - buff2, buff2, end1 - buff1, buff1);
}
+ if (LV_IS_BASE_VAR(src))
+ { /* source is unsubscripted. check if source is empty */
+ op_fndata(src, &tmp_mval);
+ dollardata_src = MV_FORCE_INTD(&tmp_mval);
+ if (0 == dollardata_src)
+ { /* NOOP - merge with empty unsubscripted source local variable */
+ UNDO_ACTIVE_LV(actlv_merge_desc_check3); /* kill "dst" and parents as applicable if $data(dst)=0 */
+ return 0;
+ }
+ }
}
return 1;
}
diff --git a/sr_port/merrors.msg b/sr_port/merrors.msg
index 9345641..2139dd1 100644
--- a/sr_port/merrors.msg
+++ b/sr_port/merrors.msg
@@ -1,6 +1,6 @@
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
-! Copyright 2001, 2013 Fidelity Information Services, Inc !
+! Copyright 2001, 2014 Fidelity Information Services, Inc !
! !
! This source code contains the intellectual property !
! of its copyright holder(s), and is made available !
@@ -204,8 +204,8 @@ DBOPNERR <Error opening database file !AD>/error/fao=2!/ansi=0
DBRDERR <Cannot read database file !AD after opening>/error/fao=2!/ansi=0
CCEDUMPNOW <>/fatal/fao=0!/ansi=0
DEVPARINAP <Device parameter inappropriate to this command>/error/fao=0!/ansi=0
-RECORDSTAT <!AD:!_ Key cnt: !UL max subsc len: !UL max rec len: !UL max node len: !UL>/info/fao=6!/ansi=0
-NOTGBL <!_!AD!/!_!_!_"^" Expected>/error/fao=2!/ansi=0
+RECORDSTAT <!AD:!_ Key cnt: !@ZQ max subsc len: !UL max rec len: !UL max node len: !UL>/info/fao=6!/ansi=0
+NOTGBL <Expected a global variable name starting with an up-arrow (^): !AD>/error/fao=2!/ansi=0
DEVPARPROT <The protection specification is invalid>/error/fao=0!/ansi=0
PREMATEOF <Premature end of file detected>/error/fao=0!/ansi=0
GVINVALID <!_!AD!/!_!_!_Invalid global name>/error/fao=2!/ansi=0
@@ -257,7 +257,7 @@ GVSUBOFLOW <Maximum combined length of subscripts exceeded>/error/fao=0!/ansi=0
GVUNDEF <Global variable undefined: !AD>/error/fao=2!/ansi=7
TRANSNEST <Maximum transaction nesting levels exceeded>/error/fao=0!/ansi=0
INDEXTRACHARS <Indirection string contains extra trailing characters>/error/fao=0!/ansi=0
-UNUSEDMSG260 <INDMAXNEST Last used in V6.0-000>/error/fao=0!/ansi=0
+CORRUPTNODE <Corrupt input in Record # !UL, Key #!UL; resuming with next global node>/error/fao=2!/ansi=0
INDRMAXLEN <Maximum length !UL of an indirection argument was exceeded>/error/fao=1!/ansi=0
INSFFBCNT <Insufficient byte count quota left for requested operation>/error/fao=0!/ansi=0
INTEGERRS <Database integrity errors>/error/fao=0!/ansi=0
@@ -806,7 +806,7 @@ MUKILLIP <Kill in progress indicator is set for file !AD - this !AD operation is
JNLRDONLY <Journal file !AD read only>/error/fao=2!/ansi=0
ANCOMPTINC <Deviceparameter !AD is not compatible with any other deviceparameters in the !AD command>/error/fao=4!/ansi=0
ABNCOMPTINC <Deviceparameter !AD and deviceparameter !AD are not compatible in the !AD command>/error/fao=6!/ansi=0
-UNUSEDMSG809 <GTMSECSHRLOGF last used in V5.5-000>/error/fao=0!/ansi=0
+RECLOAD <Error loading record number: !UL!/>/error/fao=1!/ansi=0
SOCKNOTFND <Socket !AD not found>/error/fao=2!/ansi=0
CURRSOCKOFR <Current socket of index !UL is out of range. There are only !UL sockets.>/error/fao=2!/ansi=0
SOCKETEXIST <Socket !AD already exists>/error/fao=2!/ansi=79
@@ -830,7 +830,7 @@ TOOMANYCLIENTS <GT.CM is serving the maximum number of clients. Try again later
NOEXCLUDE <None of the excluded variables exist>/info/fao=0!/ansi=0
GVINCRISOLATION <$INCREMENT cannot be performed on global ^!AD as it has NOISOLATION turned ON>/error/fao=2!/ansi=0
EXCLUDEREORG <Global: !AD is present in the EXCLUDE option. REORG will skip the global.>/warning/fao=2!/ansi=0
-REORGINC <Reorg was incomplete. Not all globals were reorged.>/error/fao=0!/ansi=0
+REORGINC <Reorg was incomplete. Not all globals were reorged.>/warning/fao=0!/ansi=0
ASC2EBCDICCONV <ASCII/EBCDIC conversion failed when calling !AD>/error/fao=2!/ansi=0
GTMSECSHRSTART <!AD - !UL : gtmsecshr failed to startup>/error/fao=3!/ansi=0
DBVERPERFWARN1 <Performance warning: Database !AD is running in compatibility mode which degrades performance. Run MUPIP REORG UPGRADE for best overall performance>/warning/fao=2!/ansi=0
@@ -986,16 +986,16 @@ REPLJNLCLOSED <Replication in jeopardy as journaling got closed for database fil
RENAMEFAIL <Rename of file !AD to !AD failed>/warning/fao=4!/ansi=0
FILERENAME <File !AD is renamed to !AD>/info/fao=4!/ansi=0
JNLBUFINFO <Pid 0x!XL!/ dsk 0x!XL free 0x!XL bytcnt 0x!XL io_in_prog 0x!XL fsync_in_prog 0x!XL!/ dskaddr 0x!XL freeaddr 0x!XL qiocnt 0x!XL now_writer 0x!XL fsync_pid 0x!XL!/filesize 0x!XL cycle 0x!XL errcnt 0x!XL wrtsize 0x!XL fsync_dskaddr 0x!XL>/info/fao=16!/ansi=0
-UNUSEDMSG989 <JNLQIOLOCKED : Last used in V4.4-000>/error/fao=0!/ansi=0
-UNUSEDMSG990 <JNLEOFPREZERO : Last used in V4.4-000>/error/fao=0!/ansi=0
+SDSEEKERR <Sequential device seek error - !AD>/error/fao=2!/ansi=0
+LOCALSOCKREQ <LOCAL socket required>/error/fao=0!/ansi=0
TPNOTACID <!AD at !AD in a final TP retry violates ACID properties of a TRANSACTION; indefinite RESTARTs may occur !AD !AD>/info/fao=8!/ansi=0
JNLSETDATA2LONG <SET journal record has data of length !UL. Target system cannot handle data more than !UL bytes.>/error/fao=2!/ansi=0
JNLNEWREC <Target system cannot recognize journal record of type !UL, last recognized type is !UL>/error/fao=2!/ansi=0
REPLFTOKSEM <Error with replication semaphores for instance file !AD>/error/fao=2!/ansi=0
-UNUSEDMSG995 <GETCWD : Last used before V4.0-001E>/error/fao=0!/ansi=0
+SOCKNOTPASSED <Socket message contained no passed socket descriptors>/error/fao=0!/ansi=0
EXTRIOERR <Error writing extract file !AD>/error/fao=2!/ansi=0
EXTRCLOSEERR <Error closing extract file !AD>/error/fao=2!/ansi=0
-UNUSEDMSG998 <TRUNCATE : Last used in V4.3-001F>/error/fao=0!/ansi=0
+CONNSOCKREQ <Socket not connected>/error/fao=0!/ansi=0
REPLEXITERR <Replication process encountered an error while exiting>/error/fao=0!/ansi=0
MUDESTROYSUC <Global section (!AD) corresponding to file !AD successfully destroyed>/info/fao=4!/ansi=0
DBRNDWN <Error during global database rundown for region !AD.!/Notify those responsible for proper database operation.>/error/fao=2!/ansi=0
@@ -1034,7 +1034,7 @@ LKENOFINISH <LKE unable to finish all requested actions>/error/fao=0!/ansi=0
NOCHLEFT <Unhandled condition exception (all handlers exhausted) - process terminating>/fatal/fao=0!/ansi=0
MULOGNAMEDEF <Logical name !AD, needed to start replication server is already defined for this job. !/Check for an existing or improperly terminated server.>/error/fao=2!/ansi=0
BUFOWNERSTUCK <Pid !UL waiting for Pid !UL to finish disk-read of block !UL [0x!XL].!/Been waiting for !UL minutes. read_in_progress=!UL : rip_latch = !UL.>/error/fao=7!/ansi=0
-ACTIVATEFAIL <Failed to activate passive source server for secondary instance !AD>/error/fao=2!/ansi=0
+ACTIVATEFAIL <Cannot activate passive source server on instance !AD while a receiver server and/or update process is running>/error/fao=2!/ansi=0
DBRNDWNWRN <Global section of database file !AD not rundown successfully by pid !UL [0x!XL]. Global section was not removed.>/warning/fao=4!/ansi=0
DLLNOOPEN <Failed to load external dynamic library !AD>/error/fao=2!/ansi=0
DLLNORTN <Failed to look up the location of the symbol !AD>/error/fao=2!/ansi=0
@@ -1076,7 +1076,7 @@ NOSUBSCRIPT <No such subscript found (!SL)>/error/fao=1!/ansi=0
SYSTEMVALUE <Invalid value for $SYSTEM (!AD)>/error/fao=2!/ansi=0
SIZENOTVALID4 <Size (in bytes) must be either 1, 2, or 4>/error/fao=0!/ansi=0
STRNOTVALID <Error: cannot convert !AD value to valid value>/error/fao=2!/ansi=0
-UNUSEDMSG1079 <RECNOCREJNL : Last used in V4.3-001F>/error/fao=0!/ansi=0
+CREDNOTPASSED <Socket message contained no passed credentials>/error/fao=0!/ansi=0
ERRWETRAP <Error while processing $ETRAP>/error/fao=0!/ansi=0
TRACINGON <Tracing already turned on>/info/fao=0!/ansi=0
CITABENV <Environment variable for call-in table !AD not set>/error/fao=2!/ansi=0
@@ -1103,10 +1103,10 @@ PATNOTFOUND <Current pattern table has no characters with pattern code !AD>/erro
INVZDIRFORM <Invalid value (!UL) specified for ZDIR_FORM>/error/fao=1!/ansi=0
ZDIROUTOFSYNC <$ZDIRECTORY !AD is not the same as its cached value !AD>/warning/fao=4!/ansi=0
GBLNOEXIST <Global !AD no longer exists>/info/fao=2!/ansi=0
-MAXBTLEVEL <Global !AD reached maximum level>/error/fao=2!/ansi=0
+MAXBTLEVEL <Global ^!AD in region !AD reached maximum level>/error/fao=4!/ansi=0
INVMNEMCSPC <Unsupported mnemonicspace !AD>/error/fao=2!/ansi=35
JNLALIGNSZCHG <Journal ALIGNSIZE is rounded up to !UL blocks (closest next higher power of two)>/info/fao=1!/ansi=0
-UNUSEDMSG1109 <MAXTRACELEVEL : last used in V5.4-002B>/error/fao=0!/ansi=0
+SEFCTNEEDSFULLB <Current side effect setting does not permit full Boolean to be turned off>/error/fao=0!/ansi=0
GVFAILCORE <A core file is being created for later analysis if necessary>/error/fao=0!/ansi=0
DBCDBNOCERTIFY <Database !AD HAS NOT been certified due to the preceding errors - rerun DBCERTIFY SCAN>/error/fao=2!/ansi=0
DBFRZRESETSUC <Freeze released successfully on database file !AD>/info/fao=2!/ansi=0
@@ -1253,7 +1253,7 @@ REPLINSTSEQORD <!AD has seqno [0x!16 at XQ] which is less than last record seqno [0
REPLINSTSTNDALN <Could not get exclusive access to replication instance file !AD>/error/fao=2!/ansi=0
REPLREQROLLBACK <Replication instance file !AD indicates abnormal shutdown or an incomplete ROLLBACK. Run MUPIP JOURNAL ROLLBACK first>/error/fao=2!/ansi=0
REQROLLBACK <Error accessing database !AD. Run MUPIP JOURNAL ROLLBACK on cluster node !AD.>/error/fao=4!/ansi=0
-UNUSEDMSG1256 <REPLUPGRADESEC : Last used in V5.4-002B>/error/fao=0!/ansi=0
+INVOBJFILE <Cannot ZLINK object file !AD due to unexpected format>/error/fao=2!/ansi=0
SRCSRVEXISTS <Source server for secondary instance !AD is already running with pid !UL>/error/fao=3!/ansi=0
SRCSRVNOTEXIST <Source server for secondary instance !AD is not alive>/error/fao=2!/ansi=0
SRCSRVTOOMANY <Cannot start more than !UL source servers in replication instance !AD>/error/fao=3!/ansi=0
@@ -1293,7 +1293,7 @@ OPCOMMISSED <!UL errors and !UL MBFULLs sending prior operator messages>/info/fa
COMMITWAITSTUCK <Pid !UL timed out after waiting !UL minute(s) for !UL concurrent GT.M process(es) to finish commits in database file !AD>/error/fao=5!/ansi=0
COMMITWAITPID <Pid !UL waited !UL minute(s) for pid !UL to finish commits to block 0x!XL in database file !AD>/error/fao=6!/ansi=0
UPDREPLSTATEOFF <Error replicating global ^!AD as it maps to database !AD which has replication turned OFF>/error/fao=4!/ansi=0
-LITNONGRAPH <M standard requires graphics in string literals>/warning/fao=0!/ansi=0
+LITNONGRAPH <M standard requires graphics in string literals; found non-printable: $ZCHAR(!AD)>/warning/fao=2!/ansi=0
DBFHEADERR8 <Database file !AD: control problem: !AD was 0x!16 at XQ expecting 0x!16 at XQ> /info /fao=6!/ansi=0
MMBEFOREJNL <BEFORE image journaling cannot be set with MM access method in database file !AD>/warning/fao=2!/ansi=0
MMNOBFORRPL <Replication cannot be used in database file !AD which uses MM access method and NOBEFORE image journaling>/warning/fao=2!/ansi=0
@@ -1414,7 +1414,7 @@ EXTRFILEXISTS <Error opening output file: !AD -- File exists>/error/fao=2!/ansi=
MUUSERECOV <Abnormal shutdown of journaled database !AD detected>/error/fao=2!/ansi=0
SECNOTSUPPLEMENTARY <!AD is a Supplementary Instance and so cannot act as a source to non-Supplementary Instance !AD >/error/fao=4!/ansi=0
SUPRCVRNEEDSSUPSRC <Instance !AD is not configured to perform local updates so it cannot act as a receiver for non-Supplementary Instance !AD>/error/fao=4!/ansi=0
-UNUSEDMSG1417 <SYNCTOSAMETYPE: Never used before so slot free for reuse>/info/fao=0!/ansi=0
+PEERPIDMISMATCH <Local socket peer with PID=!UL does not match specified PID=!UL>/error/fao=2!/ansi=0
SETITIMERFAILED <A setitimer() call returned an error status of !UL>/fatal/fao=1!/ansi=0
UPDSYNC2MTINS <Can only UPDATERESYNC with an empty instance file>/error/fao=0!/ansi=0
UPDSYNCINSTFILE <Error with instance file name specified in UPDATERESYNC qualifier>/error/fao=0!/ansi=0
@@ -1486,7 +1486,7 @@ JNLBUFFREGUPD <Journal file buffer size for region !AD has been adjusted from !U
JNLBUFFDBUPD <Journal file buffer size for database file !AD has been adjusted from !UL to !UL.>/warning/fao=4!/ansi=0
LOCKINCR2HIGH <Attempt to increment a LOCK more than !UL times>/error/fao=1!/ansi=0
LOCKIS <!_!_Resource name: !AD>/info/fao=2!/ansi=0
-LDSPANGLOINCMP <Incomplete spanning node found during load>/error/fao=0!/ansi=0
+LDSPANGLOINCMP <Incomplete spanning node found during load!/!_!_at File offset : [0x!16 at XQ]>/error/fao=1!/ansi=0
MUFILRNDWNFL2 <Database section (id = !UL) belonging to database file !AD rundown failed>/error/fao=3!/ansi=0
MUINSTFROZEN <!AD : Instance !AZ is frozen. Waiting for instance to be unfrozen before proceeding with writes to database file !AD>/info/fao=5!/ansi=0
MUINSTUNFROZEN <!AD : Instance !AZ is now Unfrozen. Continuing with writes to database file !AD>/info/fao=5!/ansi=0
@@ -1527,7 +1527,7 @@ SOCKBIND <Error in binding socket>/error/fao=0!/ansi=0
INSTFRZDEFER <Instance Freeze initiated by !AD error on region !AD deferred due to critical resource conflict>/info/fao=4!/ansi=0
REGOPENRETRY <Attempt to open region !AD (!AD) using startup shortcut failed due to conflicting database shutdown. Retrying...>/info/fao=4!/ansi=0
REGOPENFAIL <Failed to open region !AD (!AD) due to conflicting database shutdown activity>/error/fao=4!/ansi=0
-REPLINSTNOSHM <Database !AD has no active connection to a replication journal pool; please verify that the database is listed in your instance file>/error/fao=2!/ansi=0
+REPLINSTNOSHM <Database !AD has no active connection to a replication journal pool>/error/fao=2!/ansi=0
DEVPARMTOOSMALL <Deviceparameter must be greater than zero (0)>/error/fao=0!/ansi=0
REMOTEDBNOSPGBL <Database region !AD contains portion of a spanning global and so cannot point to a remote file>/error/fao=2!/ansi=0
NCTCOLLSPGBL <Database region !AD contains portion of spanning global ^!AD and so cannot support non-zero numeric collation type>/error/fao=4!/ansi=0
@@ -1546,6 +1546,33 @@ TLSCONNINFO <Failed to obtain information on the TLS/SSL connection>/warning/fao
TLSIOERROR <Error during TLS/SSL !AD operation>/error/fao=2!/ansi=0
TLSRENEGOTIATE <Failed to renegotiate TLS/SSL connection>/error/fao=0!/ansi=0
REPLNOTLS <!AD requested TLS/SSL communication but the !AD was either not started with TLSID qualifier or does not support TLS/SSL protocol>/error/fao=4!/ansi=0
+COLTRANSSTR2LONG <Output string after collation transformation is too long>/error/fao=0!/ansi=0
+SOCKPASS <Socket pass failed>/error/fao=0!/ansi=0
+SOCKACCEPT <Socket accept failed>/error/fao=0!/ansi=0
+NOSOCKHANDLE <No socket handle specified in WRITE /PASS>/error/fao=0!/ansi=0
+TRIGLOADFAIL <MUPIP TRIGGER or $ZTRIGGER operation failed. Failure code: !AD.>/error/fao=2!/ansi=0
+SOCKPASSDATAMIX <Attempt to use a LOCAL socket for both READ/WRITE and PASS/ACCEPT>/error/fao=0!/ansi=0
+NOGTCMDB <!AD does not support operation on GT.CM database region: !AD>/error/fao=4!/ansi=0
+NOUSERDB <!AD does not support operation on non-GDS format region: !AD>/error/fao=4!/ansi=0
+DSENOTOPEN <DSE could not open region !AD - see DSE startup error message for cause>/error/fao=2!/ansi=0
+ZSOCKETATTR <Attribute "!AD" invalid for $ZSOCKET function>/error/fao=2!/ansi=0
+ZSOCKETNOTSOCK <$ZSOCKET function called but device is not a socket>/error/fao=0!/ansi=0
+CHSETALREADY <CHSET !AD already specified for socket device>/error/fao=2!/ansi=0
+DSEMAXBLKSAV <DSE cannot SAVE another block as it already has the maximum of !UL>/error/fao=1!/ansi=0
+BLKINVALID <!XL is not a valid block as database file !AD has !XL total blocks>/error/fao=4!/ansi=0
+CANTBITMAP <Can't perform this operation on a bit map (block at a 200 hexadecimal boundary)>/error/fao=0!/ansi=0
+AIMGBLKFAIL <After image build for block !XL in region !AD failed in DSE or MUPIP>/error/fao=3!/ansi=0
+GTMDISTUNVERIF <Environment variable $gtm_dist (!AD) could not be verified against the executables path (!AD)>/error/fao=4!/ansi=0
+CRYPTNOAPPEND <APPEND disallowed on the encrypted file !AD>/error/fao=2!/ansi=0
+CRYPTNOSEEK <SEEK disallowed on the encrypted file !AD>/error/fao=2!/ansi=0
+CRYPTNOTRUNC <Not positioned at file start or EOF. TRUNCATE disallowed on the encrypted file !AD>/error/fao=2!/ansi=0
+CRYPTNOKEYSPEC <Key name needs to be specified with KEY, IKEY, or OKEY device parameter for encrypted I/O>/error/fao=0!/ansi=0
+CRYPTNOOVERRIDE <Cannot override IVEC and/or key without compromising integrity>/error/fao=0!/ansi=0
+CRYPTKEYTOOBIG <Specified key has length !UL, which is greater than the maximum allowed key length !UL>/error/fao=2!/ansi=0
+CRYPTBADWRTPOS <Encrypted WRITE disallowed from a position different than where the last WRITE completed>/error/fao=0!/ansi=0
+LABELNOTFND <GOTO referenced a label that does not exist>/error/fao=0!/ansi=13
+RELINKCTLERR <Error with relink control structure for $ZROUTINES directory !AD>/error/fao=2!/ansi=0
+INVLINKTMPDIR <Value for $gtm_linktmpdir is either not found or not a directory: !AD>/error/fao=2!/ansi=0
!
! If there are UNUSEDMSG* lines unused for more than one year and at least two non-patch releases, use them before adding new lines.
!
diff --git a/sr_port/mu_extr_gblout.c b/sr_port/mu_extr_gblout.c
index a31cd35..756db1a 100644
--- a/sr_port/mu_extr_gblout.c
+++ b/sr_port/mu_extr_gblout.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -127,13 +127,7 @@ boolean_t mu_extr_gblout(glist *gl_ptr, struct RAB *outrab, mu_extr_stats *st, i
if (prev_csd != cs_data)
{
prev_csd = cs_data;
- for (reg = gd_header->regions, reg_top = reg + gd_header->n_regions, index = 0;
- reg < reg_top; reg++, index++)
- {
- if (gv_cur_region == reg)
- break;
- }
- assert(gv_cur_region < reg_top);
+ index = find_reg_hash_idx(gv_cur_region);
}
/* We have to write the encrypted version of the block. Instead of encrypting the plain-text version of the
* block, we just reference the encrypted version of the block that is already maintained in sync with the
@@ -151,7 +145,7 @@ boolean_t mu_extr_gblout(glist *gl_ptr, struct RAB *outrab, mu_extr_stats *st, i
if (mu_ctrlc_occurred)
{
gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(8) ERR_RECORDSTAT, 6, LEN_AND_LIT("TOTAL"),
- st->recknt, st->keylen, st->datalen, st->reclen);
+ &st->recknt, st->keylen, st->datalen, st->reclen);
mu_ctrlc_occurred = FALSE;
}
encrypted_bp = NULL;
diff --git a/sr_port/mu_int_blk.c b/sr_port/mu_int_blk.c
index 29e7c8b..49157f5 100644
--- a/sr_port/mu_int_blk.c
+++ b/sr_port/mu_int_blk.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -60,7 +60,6 @@ GBLREF boolean_t tn_reset_this_reg;
GBLREF int disp_maxkey_errors;
GBLREF int disp_trans_errors;
GBLREF int maxkey_errors;
-GBLREF int muint_adj;
GBLREF int muint_end_keyend;
GBLREF int muint_start_keyend;
GBLREF int mu_int_plen;
@@ -71,7 +70,6 @@ GBLREF uint4 mu_int_offset[];
GBLREF uint4 mu_int_recs[];
GBLREF qw_num mu_int_size[];
GBLREF uint4 mu_int_errknt;
-GBLREF block_id mu_int_adj_prev[];
GBLREF block_id mu_int_path[];
GBLREF int4 mu_int_blks_to_upgrd;
GBLREF global_list *trees;
@@ -243,7 +241,7 @@ boolean_t mu_int_blk(
}
blk_top = blk_base + blk_size;
blk_levl = ((blk_hdr_ptr_t)blk_base)->levl;
- if (block)
+ if (block && (BML_LEVL == mu_int_root_level))
mu_int_root_level = level = blk_levl;
else if (is_root)
{
@@ -267,11 +265,7 @@ boolean_t mu_int_blk(
return FALSE;
}
if (!master_dir)
- {
- if (mu_int_adj_prev[level] <= blk + muint_adj && mu_int_adj_prev[level] >= blk - muint_adj)
- mu_int_adj[level] += 1;
- mu_int_adj_prev[level] = blk;
- }
+ CHECK_ADJACENCY(blk, level, mu_int_adj[level]);
blk_tn = ((blk_hdr_ptr_t)blk_base)->tn;
if (blk_tn >= mu_int_data.trans_hist.curr_tn)
{
@@ -280,7 +274,7 @@ boolean_t mu_int_blk(
mu_int_err(ERR_DBTNTOOLG, TRUE, TRUE, bot_key, bot_len, top_key, top_len,
(unsigned int)blk_levl);
mu_int_plen++; /* continuing, so compensate for mu_int_err decrement */
- gtm_putmsg(VARLSTCNT(3) ERR_DBTN, 1, &blk_tn);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_DBTN, 1, &blk_tn);
trans_errors++;
} else
{
@@ -397,9 +391,18 @@ boolean_t mu_int_blk(
if (!master_dir)
{ /* If NOT directory tree and this is the first key in the block,
* make sure the global name part of the key matches the name
- * corresponding to the current global variable tree.
+ * corresponding to the current global variable tree. The only
+ * exception is a MUPIP INTEG -BLOCK= in which case, trees->keysize
+ * and trees->key will be uninitialized the first time we come here.
+ * In that case, initialize them.
*/
assert(strlen(trees->key) == trees->keysize);
+ assert(block || trees->keysize);
+ if (block && !trees->keysize)
+ {
+ memcpy(trees->key, key_base, name_len);
+ trees->keysize = name_len - 1;
+ }
if (0 != memcmp(trees->key, key_base, trees->keysize + 1))
{
mu_int_err(ERR_DBINVGBL, TRUE, TRUE, bot_key, bot_len,
@@ -823,6 +826,8 @@ boolean_t mu_int_blk(
return FALSE;
}
mu_int_blks[0]++;
+ if (muint_fast && (1 == level))
+ CHECK_ADJACENCY(child, 0, mu_int_adj[0]);
}
} else
{
diff --git a/sr_port/mu_int_init.c b/sr_port/mu_int_init.c
index 5730345..407eb6d 100644
--- a/sr_port/mu_int_init.c
+++ b/sr_port/mu_int_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -60,6 +60,7 @@ boolean_t mu_int_init(void)
int gtmcrypt_errno;
gd_segment *seg;
# endif
+ sgmnt_addrs *csa;
mu_gv_cur_reg_init();
/* get filename */
@@ -68,7 +69,8 @@ boolean_t mu_int_init(void)
mupip_exit(ERR_MUNODBNAME);
if (!STANDALONE(gv_cur_region))
{
- gtm_putmsg(VARLSTCNT(4) ERR_MUSTANDALONE, 2, DB_LEN_STR(gv_cur_region));
+ csa = &FILE_INFO(gv_cur_region)->s_addrs;
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_MUSTANDALONE, 2, DB_LEN_STR(gv_cur_region));
mu_int_skipreg_cnt++;
return (FALSE);
}
@@ -78,7 +80,8 @@ boolean_t mu_int_init(void)
status = dbfilop(fc);
if (SS_NORMAL != status)
{
- gtm_putmsg(VARLSTCNT(1) status);
+ csa = &FILE_INFO(gv_cur_region)->s_addrs;
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(1) status);
mu_int_skipreg_cnt++;
return FALSE;
}
@@ -104,7 +107,7 @@ boolean_t mu_int_init(void)
if (mu_int_data.is_encrypted)
{ /* Initialize encryption and the key information for the current segment to be used in mu_int_read. */
ASSERT_ENCRYPTION_INITIALIZED; /* should have been done in mu_rndwn_file called from STANDALONE macro */
- GTMCRYPT_GETKEY(NULL, mu_int_data.encryption_hash, mu_int_encrypt_key_handle, gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(NULL, mu_int_data.encryption_hash, mu_int_encrypt_key_handle, gtmcrypt_errno);
if (0 != gtmcrypt_errno)
{
seg = gv_cur_region->dyn.addr;
diff --git a/sr_port/mu_int_reg.c b/sr_port/mu_int_reg.c
index d626c42..454f2c1 100644
--- a/sr_port/mu_int_reg.c
+++ b/sr_port/mu_int_reg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -44,44 +44,43 @@
#define MUPIP_INTEG "MUPIP INTEG"
+GBLREF boolean_t ointeg_this_reg;
GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_data mu_int_data;
+GBLREF sgmnt_data_ptr_t cs_data;
GBLREF unsigned char *mu_int_master;
-GBLREF uint4 mu_int_errknt;
GBLREF uint4 mu_int_skipreg_cnt;
-GBLREF sgmnt_data_ptr_t cs_data;
+#ifdef DEBUG
GBLREF pid_t process_id;
-GBLREF boolean_t ointeg_this_reg;
+#endif
#ifdef GTM_CRYPT
GBLREF gtmcrypt_key_t mu_int_encrypt_key_handle;
GBLREF sgmnt_addrs *cs_addrs;
#endif
#ifdef UNIX
-GBLREF boolean_t jnlpool_init_needed;
+GBLREF boolean_t jnlpool_init_needed, online_specified, preserve_snapshot;
GBLREF util_snapshot_ptr_t util_ss_ptr;
-GBLREF boolean_t preserve_snapshot;
-GBLREF boolean_t online_specified;
#endif
error_def(ERR_BUFFLUFAILED);
-error_def(ERR_DBRDONLY);
-error_def(ERR_MUKILLIP);
error_def(ERR_SSV4NOALLOW);
error_def(ERR_SSMMNOALLOW);
void mu_int_reg(gd_region *reg, boolean_t *return_value)
{
- sgmnt_addrs *csa;
+ boolean_t read_only, was_crit;
freeze_status status;
node_local_ptr_t cnl;
- boolean_t need_to_wait = FALSE, read_only, was_crit;
+ sgmnt_addrs *csa;
+# ifdef DEBUG
+ boolean_t need_to_wait = FALSE;
int trynum;
uint4 curr_wbox_seq_num;
+# endif
# ifdef GTM_CRYPT
- int gtmcrypt_errno;
gd_segment *seg;
+ int gtmcrypt_errno;
# endif
-
*return_value = FALSE;
UNIX_ONLY(jnlpool_init_needed = TRUE);
ESTABLISH(mu_int_reg_ch);
@@ -111,8 +110,9 @@ void mu_int_reg(gd_region *reg, boolean_t *return_value)
# ifdef GTM_CRYPT
if (cs_data->is_encrypted)
{ /* Initialize mu_int_encrypt_key_handle to be used in mu_int_read */
+ assert(csa == cs_addrs);
ASSERT_ENCRYPTION_INITIALIZED; /* should have happened in db_init() */
- GTMCRYPT_GETKEY(cs_addrs, cs_data->encryption_hash, mu_int_encrypt_key_handle, gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(cs_addrs, cs_data->encryption_hash, mu_int_encrypt_key_handle, gtmcrypt_errno);
if (0 != gtmcrypt_errno)
{
seg = gv_cur_region->dyn.addr;
@@ -135,7 +135,7 @@ void mu_int_reg(gd_region *reg, boolean_t *return_value)
ointeg_this_reg = FALSE; /* Turn off ONLINE INTEG for this region */
if (online_specified)
{
- gtm_putmsg(VARLSTCNT(4) ERR_SSV4NOALLOW, 2, DB_LEN_STR(gv_cur_region));
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_SSV4NOALLOW, 2, DB_LEN_STR(gv_cur_region));
util_out_print(NO_ONLINE_ERR_MSG, TRUE);
mu_int_skipreg_cnt++;
return;
@@ -148,6 +148,7 @@ void mu_int_reg(gd_region *reg, boolean_t *return_value)
switch (status)
{
case REG_ALREADY_FROZEN:
+ UNIX_ONLY(if (csa->read_only_fs) break);
util_out_print("!/Database for region !AD is already frozen, not integing",
TRUE, REG_LEN_STR(gv_cur_region));
mu_int_skipreg_cnt++;
@@ -157,6 +158,7 @@ void mu_int_reg(gd_region *reg, boolean_t *return_value)
status = region_freeze(gv_cur_region, TRUE, FALSE, FALSE);
if (REG_ALREADY_FROZEN == status)
{
+ UNIX_ONLY(if (csa->read_only_fs) break);
util_out_print("!/Database for region !AD is already frozen, not integing",
TRUE, REG_LEN_STR(gv_cur_region));
mu_int_skipreg_cnt++;
@@ -178,7 +180,8 @@ void mu_int_reg(gd_region *reg, boolean_t *return_value)
{
if (!read_only && !wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH))
{
- gtm_putmsg(VARLSTCNT(6) ERR_BUFFLUFAILED, 4, LEN_AND_LIT(MUPIP_INTEG), DB_LEN_STR(gv_cur_region));
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_BUFFLUFAILED, 4, LEN_AND_LIT(MUPIP_INTEG),
+ DB_LEN_STR(gv_cur_region));
mu_int_skipreg_cnt++;
return;
}
@@ -201,10 +204,12 @@ void mu_int_reg(gd_region *reg, boolean_t *return_value)
ointeg_this_reg = FALSE; /* Turn off ONLINE INTEG for this region */
assert(process_id != cnl->in_crit); /* Ensure ss_initiate released the crit before returning */
assert(process_id != cs_data->freeze); /* Ensure region is unfrozen before returning from ss_initiate */
+ assert(INTRPT_IN_SS_INITIATE != intrpt_ok_state); /* Ensure ss_initiate released intrpt_ok_state */
return;
}
assert(process_id != cnl->in_crit); /* Ensure ss_initiate released the crit before returning */
assert(process_id != cs_data->freeze); /* Ensure region is unfrozen before returning from ss_initiate */
+ assert(INTRPT_IN_SS_INITIATE != intrpt_ok_state); /* Ensure ss_initiate released intrpt_ok_state */
# if defined(DEBUG)
curr_wbox_seq_num = 1;
cnl->wbox_test_seq_num = curr_wbox_seq_num; /* indicate we took the next step */
diff --git a/sr_port/mur_interactive.c b/sr_port/mu_interactive.c
similarity index 76%
rename from sr_port/mur_interactive.c
rename to sr_port/mu_interactive.c
index 84786f4..a3162fc 100644
--- a/sr_port/mur_interactive.c
+++ b/sr_port/mu_interactive.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -8,31 +8,15 @@
* the license, please stop and do not read further. *
* *
****************************************************************/
-
#include "mdef.h"
-#include "gtm_ctype.h"
-#include "gtm_string.h"
-#ifdef UNIX
-#include "gtm_stdio.h"
-#else
-#include <descrip.h>
-#endif
-
#include "gdsroot.h"
#include "gdsblk.h"
#include "gdsbt.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsfhead.h"
-#include "filestruct.h"
-#include "jnl.h"
-#include "buddy_list.h"
-#include "hashtab_int4.h" /* needed for muprec.h */
-#include "hashtab_int8.h" /* needed for muprec.h */
-#include "hashtab_mname.h" /* needed for muprec.h */
-#include "muprec.h"
#include "util.h"
-
+#include "mu_interactive.h"
#define PROCEED_PROMPT "Proceed? [Y/N]: "
@@ -40,17 +24,17 @@
#define YES_STRING "YES"
#define NO_STRING "NO"
-
-boolean_t mur_interactive(void)
+boolean_t mu_interactive(caddr_t message)
{
boolean_t done = FALSE, mur_error_allowed;
unsigned short len;
int index;
char res[8];
UNIX_ONLY(char *fgets_res;)
+ UNIX_ONLY(util_out_print(PROCEED_PROMPT, TRUE);)
VMS_ONLY($DESCRIPTOR (dres, res);)
VMS_ONLY($DESCRIPTOR (dprm, PROCEED_PROMPT);)
- UNIX_ONLY(util_out_print(PROCEED_PROMPT, TRUE);)
+
while (FALSE == done)
{
VMS_ONLY(lib$get_input(&dres, &dprm, &len);)
@@ -86,7 +70,6 @@ boolean_t mur_interactive(void)
# endif
}
if (FALSE == mur_error_allowed)
- util_out_print("Recovery terminated by operator", TRUE);
-
+ util_out_print(message, TRUE);
return (mur_error_allowed);
}
diff --git a/sr_port/gtm_imagetype_init.h b/sr_port/mu_interactive.h
similarity index 68%
copy from sr_port/gtm_imagetype_init.h
copy to sr_port/mu_interactive.h
index a46766a..85a055b 100644
--- a/sr_port/gtm_imagetype_init.h
+++ b/sr_port/mu_interactive.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010 Fidelity Information Services, Inc *
+ * Copyright 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -8,10 +8,9 @@
* the license, please stop and do not read further. *
* *
****************************************************************/
+#ifndef _MU_INTERACTIVE_H_
+#define _MU_INTERACTIVE_H_
-#ifndef GTM_IMAGETYPE_INIT_INCLUDED
-#define GTM_IMAGETYPE_INIT_INCLUDED
-
-void gtm_imagetype_init(enum gtmImageTypes img_type);
+boolean_t mu_interactive(caddr_t message);
#endif
diff --git a/sr_port/mu_reorg.c b/sr_port/mu_reorg.c
index ce1bd28..163228a 100644
--- a/sr_port/mu_reorg.c
+++ b/sr_port/mu_reorg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -351,7 +351,8 @@ boolean_t mu_reorg(glist *gl_ptr, glist *exclude_glist_ptr, boolean_t *resume,
status = mu_split(level, i_max_fill, d_max_fill, &cnt1, &cnt2);
if (cdb_sc_maxlvl == status)
{
- gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_MAXBTLEVEL, 2, gn->len, gn->addr);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(6) ERR_MAXBTLEVEL, 4, gn->len, gn->addr,
+ REG_LEN_STR(gv_cur_region));
reorg_finish(dest_blk_id, blks_processed, blks_killed, blks_reused,
file_extended, lvls_reduced, blks_coalesced, blks_split, blks_swapped);
return FALSE;
diff --git a/sr_port/mubfndreg.c b/sr_port/mubfndreg.c
deleted file mode 100644
index 031d508..0000000
--- a/sr_port/mubfndreg.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************
- * *
- * Copyright 2001, 2008 Fidelity Information Services, Inc *
- * *
- * This source code contains the intellectual property *
- * of its copyright holder(s), and is made available *
- * under a license. If you do not know the terms of *
- * the license, please stop and do not read further. *
- * *
- ****************************************************************/
-
-#include "mdef.h"
-
-#include "gtm_string.h"
-
-#include "gdsroot.h"
-#include "gtm_facility.h"
-#include "fileinfo.h"
-#include "gdsbt.h"
-#include "gdsfhead.h"
-#include "util.h"
-#include "mupipbckup.h"
-
-GBLREF gd_addr *gd_header;
-
-gd_region *mubfndreg(unsigned char *regbuf,unsigned short len)
-{
- gd_region *reg;
- unsigned short i;
- boolean_t found;
-
- found = FALSE;
- for (i = 0, reg = gd_header->regions; i < gd_header->n_regions ;i++, reg++)
- {
- if (len == reg->rname_len && (memcmp(®->rname[0],&(regbuf[0]),len) == 0))
- {
- found = TRUE;
- break;
- }
- }
- if (!found)
- {
- util_out_print("REGION !AD not found.", TRUE, len, regbuf);
- return FALSE;
- }
- if (reg->dyn.addr->acc_meth == dba_usr)
- {
- util_out_print("REGION !AD maps to a non-GDS database. Specified function does not apply to a non-GDS database.",
- TRUE, len, regbuf);
- return FALSE;
- }
- return reg;
-}
diff --git a/sr_port/muext_rec_table.h b/sr_port/muext_rec_table.h
index a61de53..7886929 100644
--- a/sr_port/muext_rec_table.h
+++ b/sr_port/muext_rec_table.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -27,5 +27,6 @@ MUEXT_TABLE_ENTRY (MUEXT_TSTART, '0', '8') /* 08 : TSTART record */
MUEXT_TABLE_ENTRY (MUEXT_TCOMMIT, '0', '9') /* 09 : TCOMMIT record */
MUEXT_TABLE_ENTRY (MUEXT_ZKILL, '1', '0') /* 10 : ZKILL record */
MUEXT_TABLE_ENTRY (MUEXT_ZTWORM, '1', '1') /* 11 : ZTWORMHOLE record */
-MUEXT_TABLE_ENTRY (MUEXT_ZTRIG, '1', '2') /* 12 : ZTRIGGER record */
+MUEXT_TABLE_ENTRY (MUEXT_ZTRIG, '1', '2') /* 12 : ZTRIGGER record */
+MUEXT_TABLE_ENTRY (MUEXT_LGTRIG, '1', '3') /* 13 : LGTRIG record */
/* End of table (enforces last record has line end) */
diff --git a/sr_port/muextr.h b/sr_port/muextr.h
index dac85c5..a6efe99 100644
--- a/sr_port/muextr.h
+++ b/sr_port/muextr.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,6 +9,8 @@
* *
****************************************************************/
+#include "wbox_test_init.h"
+
typedef struct glist_struct
{
struct glist_struct *next;
@@ -47,7 +49,7 @@ typedef struct glist_struct
gbl_name_buff[gbl_buff_index++] = ')'; \
} \
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_RECORDSTAT, 6, gbl_buff_index, gbl_name_buff, \
- GBLSTAT.recknt, GBLSTAT.keylen, GBLSTAT.datalen, GBLSTAT.reclen); \
+ &GBLSTAT.recknt, GBLSTAT.keylen, GBLSTAT.datalen, GBLSTAT.reclen); \
}
#define DO_OP_GVNAME(GL_PTR) \
@@ -65,10 +67,10 @@ typedef struct glist_struct
typedef struct
{
- int recknt;
- int reclen;
- int keylen;
- int datalen;
+ gtm_uint64_t recknt;
+ uint4 reclen;
+ uint4 keylen;
+ uint4 datalen;
} mu_extr_stats;
#define MU_EXTR_STATS_INIT(TOT) \
@@ -76,15 +78,17 @@ typedef struct
TOT.recknt = TOT.reclen = TOT.keylen = TOT.datalen = 0; \
}
-#define MU_EXTR_STATS_ADD(DST, SRC) \
-{ \
- DST.recknt += SRC.recknt; \
- if (DST.reclen < SRC.reclen) \
- DST.reclen = SRC.reclen; \
- if (DST.keylen < SRC.keylen) \
- DST.keylen = SRC.keylen; \
- if (DST.datalen < SRC.datalen) \
- DST.datalen = SRC.datalen; \
+#define MU_EXTR_STATS_ADD(DST, SRC) \
+{ \
+ GTM_WHITE_BOX_TEST(WBTEST_FAKE_BIG_EXTRACT, SRC.recknt, (SRC.recknt << 31)); \
+ assert((DST.recknt + SRC.recknt) >= DST.recknt); /* overflow check */ \
+ DST.recknt += SRC.recknt; \
+ if (DST.reclen < SRC.reclen) \
+ DST.reclen = SRC.reclen; \
+ if (DST.keylen < SRC.keylen) \
+ DST.keylen = SRC.keylen; \
+ if (DST.datalen < SRC.datalen) \
+ DST.datalen = SRC.datalen; \
}
typedef struct coll_hdr_struct
@@ -143,6 +147,7 @@ typedef struct coll_hdr_struct
char *mu_extr_ident(mstr *a);
void mu_extract(void);
int mu_extr_getblk(unsigned char *ptr, unsigned char *encrypted_buff_ptr);
+int find_reg_hash_idx(gd_region *reg);
#if defined(GTM_CRYPT)
boolean_t mu_extr_gblout(glist *gl_ptr, mu_extr_stats *st, int format, boolean_t is_any_file_encrypted);
#elif defined(UNIX)
@@ -225,4 +230,3 @@ boolean_t mu_extr_gblout(glist *gl_ptr, struct RAB *outrab, mu_extr_stats *st, i
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status); \
}
#endif
-
diff --git a/sr_port/mumps.hlp b/sr_port/mumps.hlp
index c40d0ec..23aa203 100644
--- a/sr_port/mumps.hlp
+++ b/sr_port/mumps.hlp
@@ -114,36 +114,10 @@
run-time system suspends execution of a routine immediately and transfers
control to Direct Mode or to a user-written error routine.
-4 Error_Processing
- Error Processing
-
- The GT.M compiler detects and reports syntax errors at the following
- times:
-
- * Compile-time - while producing the object module from a source file
- * Run-time - while compiling code for M indirection and XECUTEs
- * Run-time - when the user is working in Direct Mode.
-
- The compile-time error message format displays the line containing the
- error and the location of the error on the line. The error message also
- indicates what was incorrect about the M statement.
-
- GT.M can not detect certain types of errors associated with indirection,
- the functioning of I/O devices, and program logic until run-time.
-
- The compile-as-written feature allows compilation to continue and produces
- an object module despite errors in the code. This permits testing of other
- pathways through the code. The errors are reported at run-time, when GT.M
- encounters them in the execution path.
-
- The GT.M run-time system recognizes execution errors and reports them when
- they occur. It also reports errors flagged by the compiler when they occur
- in the execution path.
-
2 Copyright
Copyright
- Copyright 1987 - 2003, 2013
+ Copyright 1987 - 2003, 2013 - 2014
Fidelity Information Services, Inc. All rights reserved.
@@ -433,22 +407,28 @@
| Kill * | Removes the association between its arguments, |
| | and any associated arrays. |
|----------------------+-------------------------------------------------|
+ | | When QUIT * terminates an extrinsic function or |
+ | | an extrinsic special variable, it always |
+ | Quit * | returns an alias container. For more |
+ | | information, refer to the description of QUIT * |
+ | | in "Quit". |
+ |----------------------+-------------------------------------------------|
| ZWrite / ZSHow "V" | Produces Alias Variables format output. |
|----------------------+-------------------------------------------------|
| New | For the scope of the NEW, a NEW of a name |
| | suspends its alias association. |
|----------------------+-------------------------------------------------|
| | Create a scope in which only one association |
- | Exclusive New | between a name or an lvn and an array may be |
+ | Exclusive New | between an lname or an lvn and an array may be |
| | visible. |
|----------------------+-------------------------------------------------|
| | returns a unique identifier (handle) for the |
- | $ZAHandle() | array associated with a name or an alias |
+ | $ZAHandle() | array associated with an lname or an alias |
| | container; for an subscripted lvn, it returns |
| | an empty string. |
|----------------------+-------------------------------------------------|
| | Extends $DATA() to reflects the current alias |
- | $ZDATA() | state of the lvn or name argument to identify |
+ | $ZDATA() | state of the lvn or lname argument to identify |
| | alias and alias container variables. |
|----------------------+-------------------------------------------------|
| View and $View() | |
@@ -461,6 +441,148 @@
| | transaction RESTART. |
+------------------------------------------------------------------------+
+3 SET_*_and_QUIT_*_Examples
+ SET * and QUIT * Examples
+
+ The following table show the type of data movement of alias and alias
+ container variables from QUIT * in a function to a SET * target:
+
+ +-------------------------------------------------------------------------+
+ | | QUIT * | SET * | Result |ZWRITE |
+ |----------------------+----------+-------------------+-----------+-------|
+ | |Creates an|Dereferences the |Same as set| |
+ |set *a=$$makealias(.c)|alias |alias container |*a=c |*c=a |
+ | |container | | | |
+ |----------------------+----------+-------------------+-----------+-------|
+ |set |Creates an|Dereferences the |Same as set| |
+ |*a(1)=$$makealias(.c) |alias |alias container |*a(1)=c |*a(1)=c|
+ | |container | | | |
+ |----------------------+----------+-------------------+-----------+-------|
+ | |Returns an|Copies the alias |Same as set| |
+ |set *a=$$makecntnr(.c)|alias |container |*a=c(1) |*c=a |
+ | |container | | | |
+ |----------------------+----------+-------------------+-----------+-------|
+ |set |Returns an|Copies the alias |Same as set| |
+ |*a(1)=$$makecntnr(.c) |alias |container |*a(1)=c(1) |*a(1)=c|
+ | |container | | | |
+ +-------------------------------------------------------------------------+
+
+ The makealias function returns an alias of the argument:
+
+ makealias(var)
+ quit *var
+
+ The makecntr function returns an alias container of the argument:
+
+ makecntnr(var)
+ new cont
+ set *cont(1)=var
+ quit *cont(1)
+
+3 Examples
+ Examples
+
+ Example
+
+ GTM>Set A=1,*B=A ; Create an array and an association
+
+ GTM>ZWRite ; Show that the array and association exist
+ A=1 ;*
+ *B=A
+ GTM>Kill *A ; Remove the association for A - it now has no association and no array
+
+ GTM>ZWRite ; B is a traditional local variable
+ B=1
+ Example:
+ GTM>Set A=2 ; add a value for A
+
+ GTM>ZWRite ; A and B have different values and both are traditional local variables
+ A=2
+ B=1
+ GTM>
+
+ KILL on the other hand, removes data in the array (and possibly the array
+ itself) without affecting any alias association.
+
+ GTM>Set A=2,*B=A ; Create an array and an association
+
+ GTM>ZWRite ; Both array and association exist
+ A=2 ;*
+ *B=A
+ GTM>Kill A ; Kill the array
+
+ GTM>ZWRite ; There's no data to show - only the association
+ *B=A
+
+ GTM>Set B=3 ; Create a new value
+
+ GTM>ZWRite ; The association was unaffected by the Kill
+ A=3 ;*
+ *B=A
+ GTM>
+
+ Example:
+
+ $ /usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^killalias
+ killalias ; Demonstrate Kill * of pass-by-reference
+ ZPrint ; Print this program
+ Set A=1,C=3
+ Write "------------",!
+ Write "Initial Values:",!
+ ZWRite
+ Do K1(.A,.C) ; Pass A & C by reference
+ Write "------------",!
+ Write "Value of A is unchanged because of Kill *B, but C has changed: ",!
+ ZWRite
+ Quit
+ ;
+ K1(B,D) ; A & C are bound to B & D respectively
+ Write "------------",!
+ Write "A & B are aliases, as are C & D:",!
+ ZWRite
+ Kill *B
+ Set B=2,D=4
+ Write "------------",!
+ Write "After Kill *B, A & B are different but C & D remain associated:",!
+ ZWrite
+ Quit
+ ------------
+ Initial Values:
+ A=1
+ C=3
+ ------------
+ A & B are aliases, as are C & D:
+ A=1 ;*
+ *B=A
+ C=3 ;*
+ *D=C
+ ------------
+ After Kill *B, A & B are different but C & D remain associated:
+ A=1
+ B=2
+ C=4 ;*
+ *D=C
+ ------------
+ Value of A is unchanged because of Kill *B, but C has changed:
+ A=1
+ C=4
+ Example:
+ GTM>Set A=1,*B=A ; Create an array and association
+ GTM>ZWRite ; Verify that it's there
+ A=1 ;*
+ *B=A
+
+ GTM>Kill (A) ; Kill everything except A
+
+ GTM>ZWRite ; Demonstrate that A also has no array
+
+ GTM>Set A=2 ; Create an array
+
+ GTM>ZWRite ; The association survived the Kill
+ A=2 ;*
+ *B=A
+ GTM>
+
3 Examples
Examples
@@ -986,22 +1108,20 @@
| | in Unicode may need to implement their own |
| | collation functions. |
|------------------------+-----------------------------------------------|
- | | When the ICHSET for a device is not "M", if |
- | | BOM (U+FEFF) is at the beginning of the |
- | | initial input for a file or data stream, GT.M |
- | | uses it to determine the endian if the ICHSET |
- | | is UTF-16 and checks for agreement with |
- | | ICHSET UTF-16BE or UTF-16LE. |
+ | | When ICHSET is UTF-16, GT.M uses BOM (U+FEFF) |
+ | | to automatically determine the endianess. For |
+ | | this to happen, the BOM must appear at the |
+ | | beginning of the file or data stream. If BOM |
+ | | is not present, GT.M assumes big endianess. |
+ | | SEEK or APPEND operations require specifying |
+ | | the endianess (UTF-16LE or UTF-16BE) because |
+ | | they do not go to the beginning of the file |
+ | | or data stream to automatically determine the |
+ | | endianess. When endianess is not specified, |
+ | | SEEK or APPEND assume big endianess. |
| | |
- | | If character set for a device is UTF-16, GT.M |
- | | uses BOM (U+FEFF) to determine the endians. |
- | | For this to happen, the BOM must be at at the |
- | | beginning of the initial input for a file or |
- | | data stream. If there is no BOM present, GT.M |
- | | assumes big endianess. |
- | Unicode Byte Order | |
- | Marker (BOM) | If the character set of a device is UTF-8, |
- | | GT.M checks for and ignores a BOM on input. |
+ | Unicode Byte Order | If the character set of a device is UTF-8, |
+ | Marker (BOM) | GT.M checks for and ignores a BOM on input. |
| | |
| | If the BOM does not match the character set |
| | specified at device OPEN, GT.M produces an |
@@ -1172,76 +1292,6 @@
feature provides immediate turnaround for rapid program development and
maintenance.
-2 Overview
- Overview
-
- This section provides an overview of the steps involved in generating
- executable programs in GT.M.
-
- The steps begin with your initial use of GT.M. The first two steps are
- part of your initial setup and will generally be performed only the first
- time you use GT.M. The remaining steps are those you will use regularly
- when generating your programs.
-
- Each of these remaining steps can be performed either from the GT.M prompt
- or the shell prompt. To clearly describe the two ways to perform each
- step, this section is set up in the format of a table with one column
- illustrating the GT.M method, and one column illustrating the shell
- method.
-
- +------------------------------------------------------------------------+
- | Creating a GT.M Routine |
- |------------------------------------------------------------------------|
- | | define |
- | | |
- | 1) Define environment | gtm_dist |
- | variables (shell) | |
- | | gtmgbldir |
- | | |
- | | gtmroutines |
- |-----------------------+------------------------------------------------|
- | 2) Prepare database | define Global Directory with GDE, |
- | (GT.M) | |
- | | create database with MUPIP CREATE |
- |-----------------------+------------------------------------------------|
- | - | SHELL | GT.M |
- |-----------------------+-----------------------+------------------------|
- | 3) Create/Edit | Create file with UNIX | ZEDIT "routine" .m |
- | routine | editor; assign .m | extension added by |
- | | extension | GT.M |
- |-----------------------+-----------------------+------------------------|
- | 4) Compile routine | invoke mumps | ZLINK "routine" |
- | | routine.m | |
- |-----------------------+-----------------------+------------------------|
- | | invoke mumps -run | |
- | | routine | Do ^routine calls from |
- | 5) Execute routine | | other routines invoke |
- | | calls from other | auto-ZLINK |
- | | routines invoke | |
- | | auto-ZLINK | |
- |-----------------------+-----------------------+------------------------|
- | | | utilize GT.M debug |
- | | | commands such as: |
- | | | |
- | | | ZGOTO |
- | | | |
- | | | ZLINK |
- | | | |
- | | | ZMESSAGE |
- | | edit file with UNIX | |
- | 6) Debug routine | editor; repeat steps | ZPRINT |
- | | 4, 5 | |
- | | | ZSHOW |
- | | | |
- | | | ZSTEP |
- | | | |
- | | | ZSYSTEM |
- | | | |
- | | | ZWRITE |
- | | | |
- | | | repeat steps 4, 5 |
- +------------------------------------------------------------------------+
-
2 Compile_Source_Program
Compile Source Program
@@ -1422,6 +1472,43 @@
The -direct_mode qualifier is incompatible with a file specification and
with all other qualifiers.
+4 dy[namic_literals]
+ dy[namic_literals]
+
+ Compiles certain data structures associated with literals used in the
+ source code in a way that they are dynamically loaded and unloaded from
+ the object code. The dynamic loading and unloading of these data
+ structures:
+
+ o Reduces the amount of private memory required by each process which in
+ turn allows more processes to execute with the same memory.
+ o In some circumstances, increases application performance by making
+ more memory available for file system buffers.
+ o Increases the CPU and stack costs of local variable processing.
+
+ With no -DYNAMIC_LITERALS specified, these data structures continue to be
+ generated when a routine is linked and stay in the private memory of each
+ process. As the use of -DYNAMIC_LITERALS increases object code size, and
+ as the dynamic loading and unloading only saves memory when the object
+ code is in shared libraries, FIS recommends restricting the use of
+ -DYNAMIC_LITERALS only when compiling object code to be loaded into shared
+ libraries.
+
+4 [no]embed_source
+ [no]embed_source
+
+ Instructs GT.M to embeds routine source code in the object code. The
+ default is NOEMBED_SOURCE. Like other GT.M compilation qualifiers, this
+ qualifier can be specified through the $ZCOMPILE intrinsic special
+ variable and gtmcompile environment variable. EMBED_SOURCE provides $TEXT
+ and ZPRINT access to the correct source code, even if the original M
+ source file has been edited or removed. Where the source code is not
+ embedded in the object code, GT.M attempts to locate the source code file.
+ If it cannot find source code matching the object code, $TEXT() returns a
+ null string. ZPRINT prints whatever source code found and also prints a
+ TXTSRCMAT message in direct mode; if it cannot find a source file, ZPRINT
+ issues a FILENOTFND error.
+
4 [no]i[gnore]
[no]i[gnore]
@@ -1473,6 +1560,27 @@
By default, the compiler operates -nolist and does not produce listings.
+4 noin[line_literals]
+ noin[line_literals]
+
+ Compiles routines to use library code in order to load literals instead of
+ generating in-line code thereby reducing the routine size. At the cost of
+ a small increase in CPU, the use of -NOINLINE_LITERAL may help counteract
+ growth in object size due to -DYNAMIC_LITERALS.
+
+ **Important**
+
+ Both -DYNAMIC_LITERALS and -NOINLINE_LITERNALS help optimize performance
+ and virtual memory usage for applications whose source code includes
+ literals. As the scalability and performance from reduced per-process
+ memory usage may or may not compensate for the incremental cost of
+ dynamically loading and unloading the data structures, and as the
+ performance of routines vs. inline code can be affected by the
+ availability of routines in cache, FIS suggests benchmarking to determine
+ the combination of qualifiers best suited to each workload. Note that
+ applications can freely mix routines compiled with different combinations
+ of qualifiers.
+
4 [no]o[bject][=filename]
[no]o[bject][=filename]
@@ -1493,18 +1601,6 @@
By default, the compiler produces object modules.
-4 s[pace]=lines
- s[pace]=lines
-
- Controls the spacing of the output in the listing file. -space=n specifies
- n-1 blank lines separating every source line in the listing file. If n<1,
- the M command uses single spacing in the listing.
-
- If this qualifier appears without the -list qualifier, the M compiler
- ignores the -space qualifier.
-
- By default, listings use single spaced output (-space=1).
-
4 r[un]
r[un]
@@ -1515,30 +1611,17 @@
may need to put the entryref in quotation marks (""). This qualifier does
not invoke the M compiler and is not compatible with any other qualifier.
-4 Summary
- Summary
+4 s[pace]=lines
+ s[pace]=lines
- +------------------------------------------+
- | mumps Command Qualifiers |
- |------------------------------------------|
- | QUALIFIER | Default |
- |--------------------------+---------------|
- | -direct_mode | N/A |
- |--------------------------+---------------|
- | -[no]i[gnore] | -ignore |
- |--------------------------+---------------|
- | -la[bels]=upper or lower | -labels=lower |
- |--------------------------+---------------|
- | -le[ngth]=n | -length=66 |
- |--------------------------+---------------|
- | -[no]li[st]=[filename] | -nolist |
- |--------------------------+---------------|
- | -[no]o[bject][=filename] | -object |
- |--------------------------+---------------|
- | -r[un] | N/A |
- |--------------------------+---------------|
- | -s[pace]=n | -space=1 |
- +------------------------------------------+
+ Controls the spacing of the output in the listing file. -space=n specifies
+ n-1 blank lines separating every source line in the listing file. If n<1,
+ the M command uses single spacing in the listing.
+
+ If this qualifier appears without the -list qualifier, the M compiler
+ ignores the -space qualifier.
+
+ By default, listings use single spaced output (-space=1).
2 Execute_Source_Program
Execute Source Program
@@ -1820,7 +1903,7 @@
Backspace: Deletes the character to the left of the cursor
- Delete: Same as backspace
+ Delete: Deletes the character under the cursor
Up-arrow: Moves to a less recent item in the RECALL list
@@ -1856,6 +1939,38 @@
mode can be toggled within a direct mode line using the terminal's INSERT
key.
+ **Important**
+
+ GT.M deletes the character under the cursor when you press the key on the
+ keyboard that sends the escape sequence which maps to the kdch1 capability
+ in your current terminfo entry (by convention, the Delete key). If the
+ current terminfo entry is missing the kdch1 capability, GT.M uses a
+ default value derived from members of the DEC VT terminal family, as it
+ does for selected other missing terminfo capabilities. In prior version,
+ in response to the escape sequence defined by kdch1, GT.M deleted the
+ character immediately on the left, akin to the Backspace key and assumed
+ an inappropriate value if a definition for kdch1 was missing. If you wish
+ to retain the prior behavior, the simplest way is to configure your
+ terminal emulator to send the same character sequences for the Delete key
+ that it does for the Backspace key. You can alternatively modify your
+ terminfo setting: for example, create an editable version of your terminfo
+ entry in a temporary file with a command such as: infocmp > /tmp/$$_$TERM
+ and edit the temporary file to replace the entry for the kbs capability
+ with the one in the kdch1 capability. Save your changes, and compile the
+ edited file into a usable terminfo entry, for example:
+
+ export TERMINFO=$HOME/.terminfo # You may need to add this to your login profile
+ profilemkdir -p $TERMINFO
+ tic /tmp/$$_$TERM # or whatever your temporary file name was
+
+ When modifying terminfo capabilities, always look for unintended changes
+ in the behavior of other applications, for example, text editors, that
+ also rely on those capabilities. In the worst case, you may need to toggle
+ between alternate terminfo entries for GT.M and other applications while
+ you evaluate different options. Also, for terminfo entries without the
+ cud1 capability, GT.M uses a linefeed when moving to the next line in
+ direct mode.
+
4 The_M_Invocation_Stack
The M Invocation Stack
@@ -1898,4619 +2013,4472 @@
The GOTO and ZGOTO commands instruct GT.M to leave Direct Mode, and
transfer control to a specified entry reference.
-2 Debug_Routine
- Debug Routine
+1 M_Lang_Features
+ M Lang Features
- To begin a debugging session on a specific routine, type the following
- command at the GTM prompt:
+ MUMPS is a general purpose language with an embedded database system. This
+ section describes the features of the language that are not covered as
+ Commands, Functions, or Intrinsic Special Variables chapters.
- GTM>DO ^routinename
+2 Data_Types
+ Data Types
- You can also begin a debugging session by pressing <CTRL-C> after running
- an M application at the shell. To invoke Direct Mode by pressing <CTRL-C>,
- process must have the Principal Device in the CENABLE state and not have
- the device set to CTRAP=$C(3).
+ M operates with a single basic data type, string. However, M evaluates
+ data using methods that vary according to context.
- When GT.M receives a <CTRL-C> command from the principal device, it
- invokes Direct Mode at the next opportunity, (usually at a point
- corresponding to the beginning of the next source line). GT.M can also
- interrupt at a FOR loop iteration or during a command of indeterminate
- duration such as LOCK, OPEN or READ. The GT.M USE command enables/disables
- the <CTRL-C> interrupt with the [NO]CENABLE deviceparameter. By default,
- GT.M starts <CTRL-C> enabled. The default setting for <CTRL-C> is
- controlled by $gtm_nocenable which controls whether <CTRL-C> is enabled at
- process startup. If $gtm_nocenable has a value of 1, "TRUE" or "YES"
- (case-insensitive), and the process principal device is a terminal,
- $PRINCIPAL is initialized to a NOCENABLE state where the process does not
- recognize <CTRL-C> as a signal to enter direct mode. No value, or other
- values of $gtm_nocenable initialize $PRINCIPAL with the CENABLE state. The
- [NO]CENABLE deviceparameter on a USE command can still control this
- characteristic from within the process.
+3 Numeric_Expressions
+ Numeric Expressions
- Each of the remaining sections of the chapter uses dmex to illustrate an
- aspect of the debugging process in GT.M.
+ When M syntax specifies a numexpr, M evaluates the data as a sequence of
+ ASCII characters that specify a number. M stops the evaluation and
+ provides the result generated from successfully evaluated characters when
+ it encounters any character that is not the following:
-3 _Routines
- Routines
+ * A digit 0-9
+ * A plus sign (+) or minus sign (-) and also the first character in the
+ string
+ * The first decimal point (.) in the string
- To create or edit a routine, use the ZEDIT command. ZEDIT invokes the
- editor specified by the EDITOR environment variable, and opens the
- specified file. dmex.m, for editing.
+3 Numeric_Accuracy
+ Numeric Accuracy
- Example:
+ GT.M provides 18 digits of accuracy, independent of the decimal point (.)
+ placement, and a numeric range from 10**(-43) to (10**47). Numbers with
+ three digits or fewer to the right of the decimal point are precise.
- GTM>ZEDIT "dmex"
+3 Integer_Expressions
+ Integer Expressions
- Once in the editor, use the standard editing commands to enter and edit
- text. When you finish editing, save the changes, which returns you to
- Direct Mode.
+ When M syntax specifies an intexpr, M evaluates the data as it would a
+ numexpr except that it stops the evaluation at any decimal point including
+ the first.
- **Note**
+3 Truth-valued_Expressions
+ Truth-valued Expressions
- For further details and examples, refer to the GT.M Programmer's Guide.
+ When M syntax specifies a tvexpr, M evaluates the data as a numeric.
+ However, it stops the evaluation and returns a true value (1) as soon as
+ it encounters a non-zero digit, otherwise it returns a false value (0). In
+ other words, M treats expressions that have a non-zero numeric value as
+ true, and expressions that have a zero numeric value as false. The sign
+ and/or decimal have no affect on the evaluation of a truth-valued
+ expression.
- GTM>ZPRINT ^dmex
- dmex;dmex - Direct Mode example
- ;
- beg for read !,"Name: ",name do name
- quit
+2 M_Names
+ M Names
- name set ln=$l(name)
- if ln,$extract("QUIT",1,ln)=$tr(name,"quit","QUIT") do quit
- . s name="Q"
- if ln<30,bame?1.a.1"-".a1","1" "1a.ap do print quit
- write !,"Please use last-name, "
- write "first-name middle-initial or 'Q' to Quit."
- quit
- print write !,$piece(name,", ",2)," ",$piece(name,", ")
- quit
- GTM>
+ M uses names for variables, LOCK command arguments, labels on lines, and
+ routine names. M names are alphanumeric and must start with an alphabetic
+ character or a percent sign (%).
- This uses the ZPRINT command to display the routine dmex.
+ The percent sign can only appear as the first character in a name. By
+ convention, names starting with percent signs are generally
+ application-independent or distinguished in some similar way.
- **Note**
+ M does not reserve any names. That is, M always distinguishes keywords by
+ context. Therefore, M permits a variable or a label called SET even though
+ the language has a command called SET.
- The example misspells the variable name as bame.
+ M names are case sensitive. That is, M treats ABC, Abc, ABc, AbC ABC, and
+ abc as six different names.
-3 Executing_M_Routines_Interactively
- Executing M Routines Interactively
+ M does not restrict the length of names in the main body of the standard.
+ However, the portability section of the standard recommends limiting names
+ to a maximum of eight (8) characters. GT.M's limit of 31 characters
+ applies to:
- To execute an M routine interactively, it is not necessary to explicitly
- compile and link your program. When you refer to an M routine that is not
- part of the current image, GT.M automatically attempts to compile and
- ZLINK the program.
+ * Local variables names
+ * Global variables names
+ * Routine names
+ * Source and object file names (not including the extension)
+ * Label names
+ * Local lock resource names
+ * Global lock resource names
- Example:
+ A trigger name is up to 28 characters and a replication instance name is
+ up to 15 characters.
- GTM>DO ^dmex
- Name: Revere, Paul
- %GTM-E-UNDEF, Undefined local variable: bame
- At M source location name+3^dmex
- GTM>
+2 Variables
+ Variables
- In this example GT.M places you in Direct Mode, but also cites an error
- found in the program with a run-time error message. In this example, it
- was a reference to bame, which is undefined.
+ M does not require predefinition of variable type or size. M variables are
+ either local or global. Any variable may be unsubscripted or subscripted.
- To see additional information about the error message, examine the $ECODE
- or $ZSTATUS special variables.
+3 Arrays_and_Subscripts
+ Arrays and Subscripts
- $ECODE is read-write intrinsic special variable that maintains a list of
- comma delimited codes that describe a history of past errors - the most
- recent ones appear at the end of the list. In $ECODE, standard errors are
- prefixed with an "M", user defined errors with a "U", and GT.M errors with
- a "Z". A GT.M code always follows a standard code.
+ In M, subscripted variables identify elements in sparse arrays. Sparse
+ arrays comprise existing subscripts and data nodes -; no space is reserved
+ for potential data nodes. These arrays generally serve logical, rather
+ than mathematical, purposes.
- $ZSTATUS is a read-write intrinsic special variable that maintains a
- string containing the error condition code and location of the last
- exception condition occurring during routine execution. GT.M updates
- $ZSTATUS only for errors found in routines and not for errors entered at
- the Direct Mode prompt.
+ M array subscripts are expressions, and are not restricted to numeric
+ values.
-3 Processing_with_Run-time_and_Syntax_Errors
- Processing with Run-time and Syntax Errors
+ The format for an M global or local variable is:
- When GT.M encounters a run-time or syntax error, it stops executing and
- displays an error message. GT.M reports the error in the message. In this
- case, GT.M reports an undefined local variable and the line in error,
- name+3^dmex. Note that GT.M re-displays the GTM> prompt so that debugging
- may continue.
+ [^]name[(expr1[,...])]
- To re-display the line and identify the error, use the ZPRINT command.
+ The body of the M standard places no restrictions on variable names.
+ However, the portability section of the standard does suggest limits on
+ the length of an individual subscript expression, and on the total length
+ of a variable name. The measurement for the length of names includes the
+ length of the global variable name itself, the sum of the lengths of all
+ the evaluated subscripts, and an allowance for an overhead of two (2)
+ times the number of subscripts. The total must not exceed 237. For
+ globals, GT.M permits this total to be modified with GDE up to 255. For
+ locals, GT.M limits the length of individual subscripts to the maximum
+ string length of 32,767. GT.M restricts the number of subscripts for local
+ or global variables to 31.
- Example:
+3 M_Collation_Sequences
+ M Collation Sequences
- GTM>ZPRINT, name+3
- %GTM-E-SPOREOL, Either a space or an end-of-line was expected but not found
- ZP, name+3
- ^_____
- GTM>
+ M collates all canonic numeric subscripts ahead of all string subscripts,
+ including strings such as those with leading zeros that represent
+ non-canonic numbers. Numeric subscripts collate from negative to positive
+ in value order. String subscripts collate in ASCII sequence. In addition,
+ GT.M allows the empty string subscript in most contexts, (the null, or
+ empty, string collates ahead of all canonic numeric subscripts).
- This example shows the result of incorrectly entering a ZPRINT command in
- Direct Mode. GT.M reports the location of the syntax error in the command
- line with an arrow. $ECODE and $ZSTATUS do not maintain this error message
- because GT.M did not produce the message during routine execution. Enter
- the correct syntax, (i.e., remove the comma) to re-display the routine
- line in error.
+ GT.M allows definition of alternative collation sequences. For complete
+ information on enabling this functionality, refer to the
+ "Internationalization" chapter in the GT.M Programmer's Guide.
- Example:
+3 Local_Variables
+ Local Variables
- GTM>WRITE $ZPOS
- name+3^dmex
+ A local variable in M refers to a variable used solely within the scope of
+ a single process. Local variable names have no leading delimiter.
- This example writes the current line position.
+ M makes a local variable available and subject to modification by all
+ routines executed within a process from the time that variable is first
+ SET until it is KILLed, or until the process stops executing M. However, M
+ "protects" a local variable after that variable appears as an argument to
+ a NEW command, or after it appears as an element in a formalist used in
+ parameter passing. When M protects a local variable, it saves a copy of
+ the variable's value and makes that variable undefined. M restores the
+ variable to its saved value during execution of the QUIT that terminates
+ the process stack level associated with the "protecting" NEW or formalist.
+ For more information on NEW and QUIT, refer to the "Commands" chapter in
+ the GT.M Programmer's Guide.
- $ZPOSITION is a read-only GT.M special variable that provides another tool
- for locating and displaying the current line. It contains the current
- entry reference as a character string in the format label+offset^routine,
- where the label is the closest preceding label. The current entry
- reference appears at the top of the M invocation stack, which can also be
- displayed with a ZSHOW "S" command.
+ M restricts the following uses of variables to local variables:
- To display the current value of every local variable defined, use the
- ZWRITE command with no arguments.
+ * FOR command control variables.
+ * Elements within the parentheses of an "exclusive" KILL.
+ * TSTART [with local variables list].
+ * A KILL with no arguments removes all current local variables.
+ * NEW command arguments.
+ * Actualnames used by pass-by-reference parameter passing.
- Example:
+3 GV_and_Resource_Name_Env
+ GV and Resource Name Env
- GTM>ZWRITE
- ln=12
- name="Revere, Paul"
+ M recognizes an optional environment specification in global names or in
+ the LOCK resource names (nrefs), which have analogous syntax. Global
+ variable names have a leading caret symbol (^) as a delimiter.
- This ZWRITE displays a listing of all the local variables currently
- defined.
+ M makes a global variable available, and subject to modification by all
+ routines executed within all processes in an environment, from the time
+ that variable is first SET until it is KILLed.
- **Note**
+3 Naked_References
+ Naked References
- ZWRITE displays the variable name. ZWRITE does not display a value for
- bame, confirming that it is not defined.
+ M accepts an abbreviation of the global name under some circumstances.
+ When the leading caret symbol (^) immediately precedes the left
+ parenthesis delimiting subscripts, the global variable reference is called
+ a naked reference. M evaluates a naked reference by prefixing the last
+ used global variable name, except for its last subscript, to the list of
+ subscripts specified by the naked reference. The prefixed portion is known
+ as the naked indicator. An attempt to use a naked reference when the prior
+ global reference does not exist, or did not contain a subscript, generates
+ an error.
-3 Correcting_Errors
- Correcting Errors
+ Because M has only one process-wide naked indicator which it maintains as
+ a side affect of every evaluation of a global variable, using the naked
+ reference requires an understanding of M execution sequence. M execution
+ generally proceeds from left to right within a line, subject to commands
+ that change the flow of control. However, M evaluates the portion of a SET
+ command argument to the right side of the equal sign before the left side.
+ Also, M does not evaluate any further $SELECT() arguments within the
+ function after it encounters a true selection argument.
- Use the ZBREAK command to establish a temporary breakpoint and specify an
- action. ZBREAK sets or clears routine-transparent breakpoints during
- debugging. This command simplifies debugging by interrupting execution at
- a specific point to examine variables, execute commands, or to start using
- ZSTEP to execute the routine line by line.
+ In general, using naked references only in very limited circumstances
+ prevents problems associated with the naked indicator.
- GT.M suspends execution during execution when the entry reference
- specified by ZBREAK is encountered. If the ZBREAK does not specify an
- expression "action", the process uses the default, BREAK, and puts GT.M
- into Direct Mode. If the ZBREAK does specify an expression "action", the
- process XECUTEs the value of "action", and does not enter Direct Mode
- unless the action includes a BREAK. The action serves as a "trace-point".
- The trace-point is silent unless the action specifies terminal output.
+3 Global_Variable_Name_Environments
+ Global Variable Name Environments
- Example:
+ M recognizes an optional environment specification in global names. The
+ environment specification designates one of some set of alternative
+ database files.
- GTM>ZBREAK name+3^dmex:"set bame=name"
+ The syntax for global variable names that include an environment
+ specification is:
- This uses a ZBREAK with an action that SETs the variable bame equal to
- name.
+ ^|expr|name[(subscript[,...])]
-3 Stepping_Through_a_Routine
- Stepping Through a Routine
+ In GT.M, the expression identifies the Global Directory for mapping the
+ global variable.
- The ZSTEP command provides a powerful tool to direct GT.M execution. When
- you issue a ZSTEP from Direct Mode, GT.M executes the program to the
- beginning of the next target line and performs the ZSTEP action.
+ Environment specifications permit easy access to global variables in
+ alternative databases, including other "copies" of active variables in the
+ current database. Environment specifications are sometimes referred to as
+ extended global syntax or extended value syntax.
- The optional keyword portion of the argument specifies the class of lines
- where ZSTEP pauses its execution, and XECUTEs the ZSTEP action specified
- by the optional action portion of the ZSTEP argument. If the action is
- specified, it must be an expression that evaluates to valid GT.M code. If
- no action is specified, ZSTEP XECUTEs the code specified by the $ZSTEP
- intrinsic special variable; by default $ZSTEP has the value "B", which
- causes GT.M to enter Direct Mode.
+ GT.M also allows:
- ZSTEP actions, that include commands followed by a BREAK, perform the
- specified action, then enter Direct Mode. ZSTEP actions that do not
- include a BREAK perform the command action and continue execution. Use
- ZSTEP actions that issue conditional BREAKs and subsequent ZSTEPs to
- perform tasks such as test for changes in the value of a variable.
+ ^|expr1,expr2|name[(subscript[,...])]
- Use ZSTEP to incrementally execute a routine or a series of routines.
- Execute any GT.M command from Direct Mode at any ZSTEP pause. To resume
- normal execution, use ZCONTINUE. Note that ZSTEP arguments are keywords
- rather than expressions, and they do not allow indirection.
+ Where the first expression identifies the Global Directory and the second
+ expression is accepted but ignored by GT.M.
- Example:
+ To improve compatibility with some other M implementations, GT.M also
+ accepts another non-standard syntax. In this syntax, the leading and
+ trailing up-bar (|) are respectively replaced by a left square-bracket ([)
+ and a right square-bracket (]). This syntax also requires expratoms,
+ rather than expressions.
- GTM>ZSTEP INTO
- Break instruction encountered during ZSTEP action
- At M source location print^dmex
- GTM>ZSTEP OUTOF
- Paul Revere
- Name: Q
- %GTM-I-BREAKZST, Break instruction encountered during ZSTEP action
- At M source location name^dmex
- GTM>ZSTEP OVER
- Break instruction encountered during ZSTEP action
- At M source location name+1^dmex
+ The formats for this non-standard syntax are:
- This example shows using the ZSTEP command to step through the routine
- dmex, starting where execution was interrupted by the undefined variable
- error. The ZSTEP INTO command executes line name+3 and interrupts
- execution at the beginning of line print.
+ ^[expratom1]name[(subscript...)]
- The ZSTEP OUTOF continues execution until line name. The ZSTEP OVER, which
- is the default, executes until it encounters the next line at this level
- on the M invocation stack. In this case, the next line is name+1. The
- ZSTEP OVER could be replaced with a ZSTEP with no argument because they do
- the same thing.
+ or
-3 Continuing_Execution_From_a_Breakpoint
- Continuing Execution From a Breakpoint
+ ^[expratom1,expratom2]name[(subscript...)]
- Use the ZCONTINUE command to continue execution from the breakpoint.
+ Where expratom1 identifies the Global Directory and expratom2 is a dummy
+ variable. Note that the first set of brackets in each format is part of
+ the syntax. The second set of square brackets is part of the meta-language
+ identifying an optional element.
Example:
- GTM>ZCONTINUE
- Paul Revere
- Name: q
- Name: QUIT
- Name: ?
- Please use last-name, first name middle-initial
- or 'Q' to Quit.
- Name:
+ $ gtmgbldir=Test.GLD
+ $ export gtmgbldir
+ $ GTM
- This uses a ZCONTINUE command to resume execution from the point where it
- was interrupted. As a result of the ZBREAK action, bame is defined and the
- error does not occur again. Because the process does not terminate as
- intended when the name read has q as a value, we need to continue
- debugging.
+ GTM>WRITE $ZGBLDIR
+ TEST.GLD
+ GTM>WRITE ^A
+ THIS IS ^A IN DATABASE RED
+ GTM>WRITE ^|"M1.GLD"|A
+ THIS IS ^A IN DATABASE WHITE
+ GTM>WRITE $ZGBLDIR
+ TEST.GLD
+ GTM>HALT
-3 Interrupting_Execution
- Interrupting Execution
+ $ echo gtmgbldir
+ TEST.GLD
- Press <CTRL-C> to interrupt execution, and return to the GTM prompt to
- continue debugging the program.
+ The statement WRITE ^|"M1.GLD"|A writes variable ^A using the Global
+ Directory, M1.GLD, but does not change the current Global Directory.
Example:
- %GTM-I-CTRLC, CTRLC_C encountered.
- GTM>
+ GTM>WRITE $ZGBLDIR
+ M1.GLD
+ GTM>WRITE ^A
+ THIS IS ^A IN DATABASE WHITE
+ GTM>WRITE ^|"M1.GLD"|A
+ THIS IS ^A IN DATABASE WHITE
- This invokes direct mode with a <CTRL-C>.
+ The statement WRITE ^|"M1.GLD"|A is equivalent to WRITE ^A.
-3 Using_the_Invocation_Stack_in_Debugging
- Using the Invocation Stack in Debugging
+ Specifying separate Global Directories does not always translate to using
+ separate databases.
- M DOs, XECUTEs, and extrinsics add a level to the invocation stack.
- Matching QUITs take a level off the stack. When GT.M executes either of
- these commands, an extrinsic function, or an extrinsic special variable,
- it "pushes" information about the new environment on the stack. When GT.M
- executes the QUIT, it "pops" the information about the discarded
- environment off the stack. It then reinstates the invoking routine
- information using the entries that have now arrived at the active end of
- the stack.
+ Example:
- **Note**
+ GTM>WRITE ^|"M1.GLD"|A,!,^|"M2.GLD"|A,!,^|"M3.GLD"
+ |A,!
+ THIS IS ^A IN DATABASE WHITE
+ THIS IS ^A IN DATABASE BLUE
+ THIS IS ^A IN DATABASE WHITE
- In the M stack model, a FOR command does not add a stack frame, and a QUIT
- that terminates a FOR loop does not remove a stack frame.
+ In this example, the WRITE does not display ^A from three GT.M database
+ files. Mapping specified by the Global Directory Editor (GDE) determines
+ the database file to which a Global Directory points.
-4 Determining_Levels_of_Nesting
- Determining Levels of Nesting
+ This result could have occurred under the following mapping:
- $STACK contains an integer value indicating the "level of nesting" caused
- by DO commands, XECUTE commands, and extrinsic functions in the M virtual
- stack.
+ ^|"M1.GLD"|A --> REGIONA --> SEGMENTA --> FILE1.DAT
+ ^|"M2.GLD"|A --> REGIONA --> SEGMENT1 --> FILE2.DAT
+ ^|"M3.GLD"|A --> REGION3 --> SEGMENT3 --> FILE1.DAT
- $STACK has an initial value of zero (0), and increments by one with each
- DO, XECUTE, or extrinsic function. Any QUIT that does not terminate a FOR
- loop or any ZGOTO command decrements $STACK. In accordance with the M
- standard, a FOR command does not increase $STACK. M routines cannot modify
- $STACK with the SET or KILL commands.
+ For more information on Global Directories, refer to the "Global Directory
+ Editor" chapter of the GT.M Administration and Operations Guide.
- Example:
+2 Literals
+ Literals
- GTM>WRITE $STACK
- 2
- GTM>WRITE $ZLEVEL
- 3
- GTM>
+ M has both string and numeric literals.
- This example shows the current values for $STACK and $ZLEVEL. $ZLEVEL is
- like $STACK except that uses one (1) as the starting level for the M
- stack, which $STACK uses zero (0), which means that $ZLEVEL is always one
- more than $STACK. Using $ZLEVEL with "Z" commands and functions, and
- $STACK with standard functions avoids the need to calculate the
- adjustment.
+3 String_Literals
+ String Literals
-4 Looking_at_the_Invocation_Stack
- Looking at the Invocation Stack
+ A string literal (strlit) is enclosed in quotation marks (" ") and can
+ contain a sequence of ASCII and Unicode characters. While the standard
+ indicates the characters must be graphic, GT.M accepts non-graphic
+ characters and, at compile-time, gives a warning. Using $CHAR() and
+ concatenate to represent non-graphic characters in strings not only avoids
+ the warning but is less error prone and makes for easier understanding. M
+ attempts to use character text that appears outside of quotation mark
+ delimiters according to context, which generally means as a local variable
+ name.
- The $STACK intrinsic special variable and the $STACK() function provide a
- mechanism to access M stack context information.
+ To include a quotation mark (") within a strlit, use a set of two
+ quotation marks ("" "").
Example:
- GTM>WRITE $STACK
- 2
- GTM>WRITE $STACK(2,"ecode")
- ,M6,Z150373850,
- GTM>WRITE $STACK(2,"place")
- name+3^dmex
- GTM>WRITE $STACK(2,"mcode")
- if ln<30,bame?1.a.1"-".a1","1" "1a.ap do print q
+ GTM>write """"
+ "
GTM>
- This example gets the value of $STACK and then uses that value to get
- various types of information about that stack level using the $STACK()
- function. The "ecode" value of the error information for level two,
- "place" is similar to $ZPOSITION, "mcode" is the code for the level.
+ The WRITE displays a single quotation mark because the first quotation
+ mark delimits the beginning of the string literal, the next two quotation
+ marks denote a single quote within the string, and the last quotation mark
+ delimits the end of the string literal.
- In addition to the $STACK intrinsic special variable, which provides the
- current stack level, $STACK(-1) gives the highest level for which $STACK()
- can return valid information. Until there is an error $STACK and
- $STACK(-1) are the same, but once $ECODE shows that there is an "current"
- error, the information returned by $STACK() is frozen to capture the state
- at the time of the error; it unfreezes after a SET $ECODE="".
+ Use the $CHAR function and the concatenation operator to include control
+ characters within a string.
Example:
- GTM>WRITE $STACK
- 2
- GTM>WRITE $STACK(-1)
- 2
+ GTM>WRITE "A"_$CHAR(9)_"B"
+ A B
GTM>
- This example shows that under the conditions created (in the above
- example), $STACK and $STACK(-1) have the same value.
+ The WRITE displays an "A," followed by a tab (<HT>), followed by a "B"
+ using $CHAR(), to introduce the non-graphic character.
+
+3 Numeric_Literals
+ Numeric Literals
- The $STACK() can return information about lower levels.
+ In M, numeric literals (numlit) are entered without surrounding
+ delimiters.
Example:
- +1^GTM$DMOD
- GTM>WRITE $STACK(1,"ecode")
- GTM>WRITE $STACK(1,"place")
- beg^dmex
- GTM>WRITE $STACK(1,"mcode")
- beg for read !,"Name:",namde do name
- GTM>
+ GTM>WRITE 1
+ 1
+ GTM> WRITE 1.1
+ 1.1
- This example shows that there was no error at $STACK level one, as well as
- the "place" and "mcode" information for that level.
+ These display numeric literals that are integer and decimal.
-3 Transferring_Routine_Control
- Transferring Routine Control
+ M also accepts numeric literals in the form of a mantissa and an exponent,
+ separated by a delimiter of "E" in uppercase. The mantissa may be an
+ integer or a decimal fraction. The integer exponent may have an optional
+ leading minus sign (-).
- The ZGOTO command transfers control from one part of the routine to
- another, or from one routine to another, using the specified entry
- reference. The ZGOTO command takes an optional integer expression that
- indicates the M stack level reached by performing the ZGOTO, and an
- optional entry reference specifying the location to where ZGOTO transfers
- control. A ZGOTO command, with an entry reference, performs a function
- similar to the GOTO command with the additional capability of reducing the
- M stack level. In a single operation, the process executes
- $ZLEVEL-intexpr, implicit QUITs from DO or extrinsic operations, and a
- GOTO operation transferring control to the named entry reference.
+ Example:
- The ZGOTO command leaves the invocation stack at the level of the value of
- the integer expression. GT.M implicitly terminates any intervening FOR
- loops and unstacks variables stacked with NEW commands, as appropriate.
+ GTM>WRITE 8E6
+ 8000000
+ GTM> WRITE 8E-6
+ .000008
+ GTM>
- ZGOTO $ZLEVEL:LABEL^ROUTINE takes the same action as GO LABEL^ROUTINE.
+ **Caution**
- ZGOTO $ZLEVEL-1 produces the same result as QUIT (followed by ZCONTINUE,
- if in Direct Mode).
+ The exponential numeric form may lead to ambiguities in the meaning of
+ subscripts. Because numeric subscripts collate ahead of string subscripts,
+ the string subscript "01E5" is not the same as the numeric subscript 01E5.
- If the integer expression evaluates to a value greater than the current
- value of $ZLEVEL, or less than zero (0), GT.M issues a run-time error.
+ GT.M handles numeric strings which are not canonical within the
+ implementation as strings unless the application specifically requests
+ they be treated as numbers. Any use in a context defined as numeric
+ elicits numeric treatment; this includes operands of numeric operators,
+ numeric literals, and some intrinsic function arguments. When the code
+ creates a large number out of range , GT.M gives a NUMOFLOW error. When
+ the code creates a small fractional number out of range GT.M treats it as
+ zero (0). The GT.M number range is (to the limit of accuracy) 1E-43 to
+ 1E47. When the application creates an in-range number that exceeds the
+ GT.M numeric accuracy of 18 significant digits, GT.M silently retains the
+ most significant digits. With standard collation, GT.M collates canonic
+ numeric strings used as subscripts numerically, while it collates
+ non-canonic numbers as strings.
- If ZGOTO has no entry reference, it performs some number of implicit QUITs
- and transfers control to the next command at the specified level. When no
- argument is specified, ZGOTO 1 is the result, and operation resumes at the
- lowest level M routine as displayed by ZSHOW "S". In the image invokedby
- mumps -direct, or a similar image, a ZGOTO without arguments returns the
- process to Direct Mode.
+2 Expressions
+ Expressions
-3 Displaying_Source_Code
- Displaying Source Code
+ The following items are legal M expression atoms (expratom). An expression
+ atom is a component of an M expression.
- Use the ZPRINT command to display source code lines selected by its
- argument. ZPRINT allows you to display the source for the current routine
- and any other related routines. Use the ZPRINT command to display the last
- call level.
+ * Local variables
+ * Global variables
+ * Intrinsic special variables
+ * Intrinsic functions
+ * Extrinsic functions
+ * Extrinsic special variables
+ * Numeric literals
+ * String literals
+ * An expression enclosed in parentheses
+ * Any of the above preceded by a unary operator
- Example:
+ In addition, any of these items may be combined with a binary operator and
+ another expression atom.
- GTM>ZPRINT beg
- beg for read !,"Name: ",name do name
+2 Operators
+ Operators
- This example uses a ZPRINT command to print the line indicated as the call
- at the top of the stack. Notice that the routine has an error in logic.
- The line starting with the label beg has a FOR loop with no control
- variable, no QUIT, and no GOTO. There is no way out of the FOR loop.
+ M has both unary and binary operators.
-3 Correcting_Errors_in_an_M_Routine
- Correcting Errors in an M Routine
+3 Precedence
+ Precedence
- Now that the routine errors have been identified, correct them in the M
- source file. Use ZEDIT to invoke the editor and open the file for editing.
- Correct the errors previously identified and enter to exit the editor.
+ All unary operations have right to left precedence.
- Example:
+ All M binary operations have strict left to right precedence. This
+ includes all arithmetic, string, and logical operations. Hierarchies of
+ operations require explicit establishment of precedence using parentheses
+ (). Although this rule is counterintuitive, it is easy to remember and has
+ no exceptions.
- GTM>ZEDIT "dmex"
- dmex;dmex - Direct Mode example
- ;
- begfor read !,"Name: ",name do name q:name="Q"
- quit
- nameset ln=$l(name)
- if ln,$e("QUIT",1,ln)=$tr(name,"quit","QUIT") d q
- . s name="Q"
- if ln<30,name?1.a.1"-".a1","1" "1a.ap do print q
- write !,"Please use last-name, "
- write "first-name middle-initial or 'Q' to Quit."
- quit
- printwrite !,$p(name,", ",2)," ",$p(name,", ")
- quit
- GTM>
+3 Arithmetic_Operators
+ Arithmetic Operators
- This example shows the final state of a ZEDIT session of dmex.m. Note that
- the infinite FOR loop at line beg is corrected.
-
-3 Relinking_the_Edited_Routine
- Relinking the Edited Routine
+ All arithmetic operators force M to evaluate the expressions to which they
+ apply as numeric. The arithmetic operators are:
- Use the ZLINK command to add the edited routine to the current image.
- ZLINK automatically recompiles and relinks the routine. If the routine was
- the most recent one ZEDITed or ZLINKed, you do not have to specify the
- routine name with the ZLINK command.
+ + as a unary operator simply forces M to evaluate the expression following
+ as numeric; as a binary operator it causes M to perform addition.
- **Caution**
+ - as a unary operator causes M to negate the expression following; as a
+ binary operator it causes M to perform subtraction.
- When you issue a DO command, GT.M determines whether the routine is part
- of the current image, and whether compiling or linking is necessary.
- Because this routine is already part of the current image, GT.M does not
- recompile or relink the edited version of the routine if you run the
- routine again without ZLINKing it first. Therefore, GT.M executes the
- previous routine image and not the edited routine.
+ * binary operator for multiplication.
- **Note**
+ ** binary operator for exponentiation.
- You may have to issue a ZGOTO or a QUIT command to remove the unedited
- version of the routine from the M invocation stack before ZLINKing the
- edited version.
+ / binary operator for fractional division.
- Example:
+ \ binary operator for integer division.
- GTM>ZLINK
- Cannot ZLINK an active routine
+ # binary operator for modulo, that is, causes M to produce the remainder
+ from integer division of the first argument by the second.
- This illustrates a GT.M error report caused by an attempt to ZLINK a
- routine that is part of the current invocation stack.
+ Remember that precedence is left to right for all arithmetic operators.
- To ZLINK the routine, remove any invocation levels for the routine off of
- the call stack. You may use the ZSHOW "S" command to display the current
- state of the call stack. Use the QUIT command to remove one level at a
- time from the call stack. Use the ZGOTO command to remove multiple levels
- off of the call stack.
+ Example:
- **Note**
+ GTM>WRITE 1+1
+ 2
+ GTM>WRITE 2-1
+ 1
+ GTM>WRITE 2*2
+ 4
+ GTM>WRITE 3**2
+ 9
+ GTM>WRITE 4/2
+ 2
+ GTM>WRITE 7
+ 2
+ GTM>WRITE 7#3
+ 1
+ GTM>
- For further details and examples, refer to the GT.M Programmer's Guide.
+ This simple example demonstrates how each arithmetic binary operation uses
+ numeric literals.
Example:
- GTM>ZSHOW "S"
- name+3^dmex ($ZTRAP) (Direct mode)
- beg^dmex (Direct mode)
- ^GTM$DMOD (Direct mode)
+ GTM>WRITE +"12ABC"
+ 12
+ GTM>WRITE --"-3-4"
+ -3
+ GTM>
- GTM>ZGOTO
+ The first WRITE shows the unary plus sign (+) operation forcing the
+ numeric evaluation of a string literal. The second WRITE demonstrates the
+ unary minus sign (-). Note the second minus sign within the string literal
+ does not cause subtraction, but rather, terminates the numeric evaluation
+ with the result of negative three (-3). Each of the leading minus signs
+ causes one negation and therefore, the result is negative three (-3).
- GTM>ZSHOW "S"
- ^GTM$DMOD (Direct mode)
- GTM>ZLINK
+3 Logical_Operators
+ Logical Operators
+
+ M logical operators always produce a result that is TRUE (1) or FALSE (0).
+ All logical operators force M to evaluate the expressions to which they
+ apply as truth-valued. The logical operators are:
- This example uses a ZSHOW "S" command to display the current state of the
- call stack. A ZGOTO command without an argument removes all the calling
- levels above the first from the stack. The ZLINK automatically recompiles
- and relinks the routine, thereby adding the edited routine to the current
- image.
+ ' unary NOT operator negates current truth-value; M accepts placement of
+ the NOT operator next to a relational operator, for example, A'=B as
+ meaning '(A=B).
-3 Re-executing_the_Routine
- Re-executing the Routine
+ &binary AND operator produces a true result only if both of the
+ expressions are true.
- Re-display the DO command using the RECALL command.
+ ! binary OR operator produces a true result if either of the expressions
+ is true.
- Execute the routine using the DO command.
+ Remember that precedence is always left to right, and that logical
+ operators have the same precedence as all other operators.
Example:
- GTM>D ^dmex
+ GTM>WRITE '0
+ 1
+ GTM>WRITE '1
+ 0
+ GTM>WRITE '5689
+ 0
+ GTM>WRITE '-1
+ 0
+ GTM>WRITE '"ABC"
+ 1
+ GTM>
- Name: Revere, Paul
- Paul Revere
- Name: q
+ The above example demonstrates the unary NOT operation. Note that any
+ non-zero numeric value is true and has a false negation.
- This example illustrates a successful execution of dmex.
+ Example:
-1 M_Lang_Features
- M Lang Features
+ GTM>WRITE 0&0
+ 0
+ GTM>WRITE 1&0
+ 0
+ GTM>WRITE 0&1
+ 0
+ GTM>WRITE 1&1
+ 1
+ GTM>WRITE 2&1
+ 1
+ GTM>WRITE 0!0
+ 0
+ GTM>WRITE 1!0
+ 1
+ GTM>WRITE 0!1
+ 1
+ GTM>WRITE 1!1
+ 1
+ GTM>WRITE 2!1
+ 1
+ GTM>
- MUMPS is a general purpose language with an embedded database system. This
- section describes the features of the language that are not covered as
- Commands, Functions, or Intrinsic Special Variables chapters.
+ The above example demonstrates all cases covered by the binary logical
+ operators.
-2 Data_Types
- Data Types
+3 String_Operators
+ String Operators
- M operates with a single basic data type, string. However, M evaluates
- data using methods that vary according to context.
+ All string operators force M to evaluate the expressions to which they
+ apply as strings. The string operator is:
-3 Numeric_Expressions
- Numeric Expressions
+ _binary operator causes M to concatenate the second expression with the
+ first expresion
- When M syntax specifies a numexpr, M evaluates the data as a sequence of
- ASCII characters that specify a number. M stops the evaluation and
- provides the result generated from successfully evaluated characters when
- it encounters any character that is not the following:
+ Example:
- * A digit 0-9
- * A plus sign (+) or minus sign (-) and also the first character in the
- string
- * The first decimal point (.) in the string
+ GTM>WRITE "B"_"A"
+ BA
+ GTM>WRITE "A"_1
+ A1
+ GTM>
-3 Numeric_Accuracy
- Numeric Accuracy
+ The above example demonstrates M concatenation.
- GT.M provides 18 digits of accuracy, independent of the decimal point (.)
- placement, and a numeric range from 10**(-43) to (10**47). Numbers with
- three digits or fewer to the right of the decimal point are precise.
+3 Numeric_Relational_Operators
+ Numeric Relational Operators
-3 Integer_Expressions
- Integer Expressions
+ M relational operators always generate a result of TRUE (1) or FALSE (0).
+ All numeric relational operators force M to evaluate the expressions to
+ which they apply as numeric. The numeric relational operators are:
- When M syntax specifies an intexpr, M evaluates the data as it would a
- numexpr except that it stops the evaluation at any decimal point including
- the first.
+ >binary arithmetic greater than
-3 Truth-valued_Expressions
- Truth-valued Expressions
+ <binary arithmetic less than
- When M syntax specifies a tvexpr, M evaluates the data as a numeric.
- However, it stops the evaluation and returns a true value (1) as soon as
- it encounters a non-zero digit, otherwise it returns a false value (0). In
- other words, M treats expressions that have a non-zero numeric value as
- true, and expressions that have a zero numeric value as false. The sign
- and/or decimal have no affect on the evaluation of a truth-valued
- expression.
+ The equal sign (=) does not force numeric evaluation, and should be viewed
+ as a string operator. However, the equal sign between two numeric values
+ tests for numeric equality.
-2 M_Names
- M Names
+ Other numeric relations are formed using the logical NOT operator
+ apostrophe (') as follows:
- M uses names for variables, LOCK command arguments, labels on lines, and
- routine names. M names are alphanumeric and must start with an alphabetic
- character or a percent sign (%).
+ '> not greater than, that is, less than or equal to
- The percent sign can only appear as the first character in a name. By
- convention, names starting with percent signs are generally
- application-independent or distinguished in some similar way.
+ '< not less than, that is, greater than or equal to
- M does not reserve any names. That is, M always distinguishes keywords by
- context. Therefore, M permits a variable or a label called SET even though
- the language has a command called SET.
+ >= greater than or equal to, that is, not less than
- M names are case sensitive. That is, M treats ABC, Abc, ABc, AbC ABC, and
- abc as six different names.
+ <= less than or equal to, that is, not greater than
- M does not restrict the length of names in the main body of the standard.
- However, the portability section of the standard recommends limiting names
- to a maximum of eight (8) characters. GT.M's limit of 31 characters
- applies to:
+ '= not equal, numeric or string operation
- * Local variables names
- * Global variables names
- * Routine names
- * Source and object file names (not including the extension)
- * Label names
- * Local lock resource names
- * Global lock resource names
+ Example:
- A trigger name is up to 28 characters and a replication instance name is
- up to 15 characters.
+ GTM>WRITE 1>2
+ 0
+ GTM>WRITE 1<2
+ 1
+ GTM>
-2 Variables
- Variables
+ The above example demonstrates the basic arithmetic relational operations.
- M does not require predefinition of variable type or size. M variables are
- either local or global. Any variable may be unsubscripted or subscripted.
+ Example:
-3 Arrays_and_Subscripts
- Arrays and Subscripts
+ GTM>WRITE 1'<2
+ 0
+ GTM>WRITE 2'<1
+ 1
+ GTM>
- In M, subscripted variables identify elements in sparse arrays. Sparse
- arrays comprise existing subscripts and data nodes -; no space is reserved
- for potential data nodes. These arrays generally serve logical, rather
- than mathematical, purposes.
+ The above example demonstrates combinations of arithmetic, relational
+ operators with the logical NOT operator.
- M array subscripts are expressions, and are not restricted to numeric
- values.
+3 String_Relational_Operators
+ String Relational Operators
- The format for an M global or local variable is:
+ M relational operators always generate a result of TRUE (1) or FALSE (0).
+ All string relational operators force M to evaluate the expressions to
+ which they apply as strings. The string relational operators are:
- [^]name[(expr1[,...])]
+ = binary operator causes M to produce a TRUE if the expressions are equal.
- The body of the M standard places no restrictions on variable names.
- However, the portability section of the standard does suggest limits on
- the length of an individual subscript expression, and on the total length
- of a variable name. The measurement for the length of names includes the
- length of the global variable name itself, the sum of the lengths of all
- the evaluated subscripts, and an allowance for an overhead of two (2)
- times the number of subscripts. The total must not exceed 237. For
- globals, GT.M permits this total to be modified with GDE up to 255. For
- locals, GT.M limits the length of individual subscripts to the maximum
- string length of 32,767. GT.M restricts the number of subscripts for local
- or global variables to 31.
+ [ binary operator causes M to produce a TRUE if the first expression
+ contains the ordered sequence of characters in the second expression.
-3 M_Collation_Sequences
- M Collation Sequences
+ ] binary operator causes M to produce a TRUE if the first expression
+ lexically follows the second expression in the character encoding
+ sequence, which by default is ASCII.
- M collates all canonic numeric subscripts ahead of all string subscripts,
- including strings such as those with leading zeros that represent
- non-canonic numbers. Numeric subscripts collate from negative to positive
- in value order. String subscripts collate in ASCII sequence. In addition,
- GT.M allows the empty string subscript in most contexts, (the null, or
- empty, string collates ahead of all canonic numeric subscripts).
+ ]] binary operator causes M to produce a TRUE if the first expression
+ lexically sorts after the second expression in the subscript collation
+ sequence.
- GT.M allows definition of alternative collation sequences. For complete
- information on enabling this functionality, refer to the
- "Internationalization" chapter in the GT.M Programmer's Guide.
-
-3 Local_Variables
- Local Variables
-
- A local variable in M refers to a variable used solely within the scope of
- a single process. Local variable names have no leading delimiter.
+ Note that all non-empty strings lexically follow the empty string, and
+ every string contains the empty string.
- M makes a local variable available and subject to modification by all
- routines executed within a process from the time that variable is first
- SET until it is KILLed, or until the process stops executing M. However, M
- "protects" a local variable after that variable appears as an argument to
- a NEW command, or after it appears as an element in a formalist used in
- parameter passing. When M protects a local variable, it saves a copy of
- the variable's value and makes that variable undefined. M restores the
- variable to its saved value during execution of the QUIT that terminates
- the process stack level associated with the "protecting" NEW or formalist.
- For more information on NEW and QUIT, refer to the "Commands" chapter in
- the GT.M Programmer's Guide.
+ Other string relations are formed using the logical NOT operator
+ apostrophe (') as follows:
- M restricts the following uses of variables to local variables:
+ '[ does not contain.
- * FOR command control variables.
- * Elements within the parentheses of an "exclusive" KILL.
- * TSTART [with local variables list].
- * A KILL with no arguments removes all current local variables.
- * NEW command arguments.
- * Actualnames used by pass-by-reference parameter passing.
+ '] does not follow, that is, lexically less than or equal to.
-3 GV_and_Resource_Name_Env
- GV and Resource Name Env
+ ']] does not sort after, that is, lexically less than or equal to in the
+ subscript collation sequence.
- M recognizes an optional environment specification in global names or in
- the LOCK resource names (nrefs), which have analogous syntax. Global
- variable names have a leading caret symbol (^) as a delimiter.
+ '= not equal, numeric or string operation.
- M makes a global variable available, and subject to modification by all
- routines executed within all processes in an environment, from the time
- that variable is first SET until it is KILLed.
+ Example:
-3 Naked_References
- Naked References
+ GTM>WRITE "A"="B"
+ 0
+ GTM>WRITE "C"="C"
+ 1
+ GTM>WRITE "A"["B"
+ 0
+ GTM>WRITE "ABC"["C"
+ 1
+ GTM>WRITE "A"]"B"
+ 0
+ GTM>WRITE "B"]"A"
+ 1
+ GTM>WRITE "A"]]"B"
+ 0
+ GTM>WRITE "B"]]"A"
+ 1
- M accepts an abbreviation of the global name under some circumstances.
- When the leading caret symbol (^) immediately precedes the left
- parenthesis delimiting subscripts, the global variable reference is called
- a naked reference. M evaluates a naked reference by prefixing the last
- used global variable name, except for its last subscript, to the list of
- subscripts specified by the naked reference. The prefixed portion is known
- as the naked indicator. An attempt to use a naked reference when the prior
- global reference does not exist, or did not contain a subscript, generates
- an error.
+ These examples demonstrate the string relational operators using string
+ literals.
- Because M has only one process-wide naked indicator which it maintains as
- a side affect of every evaluation of a global variable, using the naked
- reference requires an understanding of M execution sequence. M execution
- generally proceeds from left to right within a line, subject to commands
- that change the flow of control. However, M evaluates the portion of a SET
- command argument to the right side of the equal sign before the left side.
- Also, M does not evaluate any further $SELECT() arguments within the
- function after it encounters a true selection argument.
+ Example:
- In general, using naked references only in very limited circumstances
- prevents problems associated with the naked indicator.
+ GTM>WRITE 2]10
+ 1
+ GTM>WRITE 2]]10
+ 0
+ GTM>WRITE 0]"$"
+ 1
+ GTM>WRITE 0]]"$"
+ 0
-3 Global_Variable_Name_Environments
- Global Variable Name Environments
+ These examples illustrate that when using the primary ASCII character set,
+ the main difference in the "follows" (]) operator and the "sorts-after"
+ (]]) operator is the way they treat numbers.
- M recognizes an optional environment specification in global names. The
- environment specification designates one of some set of alternative
- database files.
+ Example:
- The syntax for global variable names that include an environment
- specification is:
+ GTM>WRITE 1=1
+ 1
+ GTM>WRITE 1=2
+ 0
+ GTM>WRITE 1="1"
+ 1
+ GTM>WRITE 1=01
+ 1
+ GTM>WRITE 1="01"
+ 0
+ GTM>WRITE 1=+"01"
+ 1
+ GTM>
- ^|expr|name[(subscript[,...])]
+ These examples illustrate the dual nature of the equal sign operator. If
+ both expressions are string or numeric, the results are straight forward.
+ However, when the expressions are mixed, the native string data type
+ prevails.
- In GT.M, the expression identifies the Global Directory for mapping the
- global variable.
+ Example:
- Environment specifications permit easy access to global variables in
- alternative databases, including other "copies" of active variables in the
- current database. Environment specifications are sometimes referred to as
- extended global syntax or extended value syntax.
+ GTM>WRITE "a"'="A"
+ 1
+ GTM>WRITE "FRED"'["RED"
+ 0
+ GTM>WRITE "ABC"']""
+ 0
- GT.M also allows:
+ These examples demonstrate combinations of the string relational operators
+ with the NOT operator.
- ^|expr1,expr2|name[(subscript[,...])]
+3 Pattern_Match_Operator
+ Pattern Match Operator
- Where the first expression identifies the Global Directory and the second
- expression is accepted but ignored by GT.M.
+ The pattern match operator (?) causes M to return a TRUE if the expression
+ ahead of the operator matches the characteristics described by the pattern
+ following the operator. The pattern is not an expression.
- To improve compatibility with some other M implementations, GT.M also
- accepts another non-standard syntax. In this syntax, the leading and
- trailing up-bar (|) are respectively replaced by a left square-bracket ([)
- and a right square-bracket (]). This syntax also requires expratoms,
- rather than expressions.
+ Patterns are made up of two elements:
- The formats for this non-standard syntax are:
+ 1. A repetition count
+ 2. A pattern code, a string literal or an alternation list
- ^[expratom1]name[(subscript...)]
+ The element following the pattern match operator may consist of an
+ indirection operator, followed by an element that evaluates to a
+ legitimate pattern.
- or
+ The repetition count consists of either a single integer literal or a
+ period (.) delimiter with optional leading and trailing integer literals.
+ A single integer literal specifies an exact repetition count. The period
+ syntax specifies a range of repetitions where the leading number is a
+ minimum and the trailing number is a maximum. When the repetition count is
+ missing the leading number, M assumes there is no minimum, (i.e., a
+ minimum of zero). When the repetition count is missing the trailing
+ number, M does not place a maximum on the number of repetitions.
- ^[expratom1,expratom2]name[(subscript...)]
+ The pattern codes are:
- Where expratom1 identifies the Global Directory and expratom2 is a dummy
- variable. Note that the first set of brackets in each format is part of
- the syntax. The second set of square brackets is part of the meta-language
- identifying an optional element.
+ A alphabetic characters upper or lower case
- Example:
+ C control characters ASCII 0-31 and 127
- $ gtmgbldir=Test.GLD
- $ export gtmgbldir
- $ GTM
+ E any character; used to pass all characters in portions of the string
+ where the pattern is not restricted
- GTM>WRITE $ZGBLDIR
- TEST.GLD
- GTM>WRITE ^A
- THIS IS ^A IN DATABASE RED
- GTM>WRITE ^|"M1.GLD"|A
- THIS IS ^A IN DATABASE WHITE
- GTM>WRITE $ZGBLDIR
- TEST.GLD
- GTM>HALT
+ L lower-case alphabetic characters, ASCII 97-122
- $ echo gtmgbldir
- TEST.GLD
+ N digits 0-9, ASCII 48-57
- The statement WRITE ^|"M1.GLD"|A writes variable ^A using the Global
- Directory, M1.GLD, but does not change the current Global Directory.
+ P punctuation, ASCII 32-47, 58-64, 91-96, 123-126
- Example:
+ U upper-case alphabetic characters, ASCII 65-90
- GTM>WRITE $ZGBLDIR
- M1.GLD
- GTM>WRITE ^A
- THIS IS ^A IN DATABASE WHITE
- GTM>WRITE ^|"M1.GLD"|A
- THIS IS ^A IN DATABASE WHITE
+ Pattern codes may be upper or lower case and may be replaced with a string
+ literal. GT.M allows the M pattern match definition of patcodes A, C, N,
+ U, L, and P to be extended or changed, (A can only be modified implicitly
+ by modifying L or U) and new patcodes added. For detailed information on
+ enabling this functionality, refer to the "Internationalization" chapter
+ in the GT.M Programmer's Guide.
- The statement WRITE ^|"M1.GLD"|A is equivalent to WRITE ^A.
+ **Note**
- Specifying separate Global Directories does not always translate to using
- separate databases.
+ The GT.M compiler accepts pattern codes other than those explicitly
+ defined above. If, at run-time, the pattern codes come into use and no
+ pattern definitions are available, GT.M issues a run-time error
+ (PATNOTFOUND). GT.M does not currently implement a mechanism for Y and Z
+ patterns and continues to treat those as compile-time syntax errors.
Example:
- GTM>WRITE ^|"M1.GLD"|A,!,^|"M2.GLD"|A,!,^|"M3.GLD"
- |A,!
- THIS IS ^A IN DATABASE WHITE
- THIS IS ^A IN DATABASE BLUE
- THIS IS ^A IN DATABASE WHITE
+ GTM>WRITE "ABC"?3U
+ 1
+ GTM>WRITE "123-45-6789"?3N1"-"2N1"-"4N
+ 1
- In this example, the WRITE does not display ^A from three GT.M database
- files. Mapping specified by the Global Directory Editor (GDE) determines
- the database file to which a Global Directory points.
+ The first WRITE has a simple one-element pattern while the second has
+ multiple elements including both codes and string literals. All the
+ repetition counts are fixed.
- This result could have occurred under the following mapping:
+ Example:
- ^|"M1.GLD"|A --> REGIONA --> SEGMENTA --> FILE1.DAT
- ^|"M2.GLD"|A --> REGIONA --> SEGMENT1 --> FILE2.DAT
- ^|"M3.GLD"|A --> REGION3 --> SEGMENT3 --> FILE1.DAT
+ I x?.E1C.E W !,"Must not contain a control character" Q
- For more information on Global Directories, refer to the "Global Directory
- Editor" chapter of the GT.M Administration and Operations Guide.
+ This example uses a pattern match to test for control characters.
-2 Literals
- Literals
+ Example:
- M has both string and numeric literals.
+ I acn?1U.20A1","1U.10A D
+ .S acn=$G((^ACX($P(acn,","),$P(acn,",",2)))
-3 String_Literals
- String Literals
+ This example uses a pattern match with implicit minimums to determine that
+ an "account number" is actually a name, and to trigger a look-up of the
+ corresponding account number in the ^ACX cross index.
- A string literal (strlit) is enclosed in quotation marks (" ") and can
- contain a sequence of ASCII and Unicode characters. While the standard
- indicates the characters must be graphic, GT.M accepts non-graphic
- characters and, at compile-time, gives a warning. Using $CHAR() and
- concatenate to represent non-graphic characters in strings not only avoids
- the warning but is less error prone and makes for easier understanding. M
- attempts to use character text that appears outside of quotation mark
- delimiters according to context, which generally means as a local variable
- name.
-
- To include a quotation mark (") within a strlit, use a set of two
- quotation marks ("" "").
-
- Example:
-
- GTM>write """"
- "
- GTM>
+ The pattern match operator accepts the alteration syntax. Alteration
+ consists of a repeat count followed by a comma-delimited list of patatoms
+ enclosed in parentheses "()". The semantic is that the pattern matches if
+ any of the listed patterns matches the operand string. For example,
+ ?1(2N1"-"7N,3N1"-"2N1"-"4N).1U might be a way to match either a social
+ security number or a taxpayer ID. Since alternation is defined as one of
+ the ways of constructing a patatom, alternation can nest (be used
+ recursively).
- The WRITE displays a single quotation mark because the first quotation
- mark delimits the beginning of the string literal, the next two quotation
- marks denote a single quote within the string, and the last quotation mark
- delimits the end of the string literal.
+ **Note**
- Use the $CHAR function and the concatenation operator to include control
- characters within a string.
+ Complex pattern matches may not be efficient to evaluate, so every effort
+ should be made to simplify any commonly used pattern and to determine if
+ more efficient alternative logic would be more appropriate.
- Example:
+2 Commands
+ Commands
- GTM>WRITE "A"_$CHAR(9)_"B"
- A B
- GTM>
+ M commands may be abbreviated to a defined prefix. Most commands have
+ arguments. However, some commands have either optional arguments or no
+ arguments. When a command has no argument and is followed by more commands
+ on the same line, at least two spaces (<SP>) must follow the command
+ without arguments. Commands that accept arguments generally accept
+ multiple arguments on the same command. M treats multiple arguments the
+ same as multiple occurrences of the same command, each with its own
+ argument.
- The WRITE displays an "A," followed by a tab (<HT>), followed by a "B"
- using $CHAR(), to introduce the non-graphic character.
+3 Postconditionals
+ Postconditionals
-3 Numeric_Literals
- Numeric Literals
+ M provides postconditionals as a tool for placing a condition on the
+ execution of a single command and, in some cases, a single command
+ argument. A postconditional consists of a colon (:) delimiter followed by
+ a truth-valued expression. When the expression evaluates to true, M
+ executes the command occurrence. When the expression evaluates to false, M
+ does not execute the command occurrence.
- In M, numeric literals (numlit) are entered without surrounding
- delimiters.
+4 Command_Postconditionals
+ Command Postconditionals
- Example:
+ Command postconditionals appear immediately following a command and apply
+ to all arguments for the command when it has multiple arguments. All
+ commands except commands that themselves have a conditional aspect accept
+ a command postconditional. Among the M standard commands, ELSE, FOR, and
+ IF do not accept command postconditionals. All the GT.M command extensions
+ accept command postconditionals.
- GTM>WRITE 1
- 1
- GTM> WRITE 1.1
- 1.1
+4 Argument_Postconditionals
+ Argument Postconditionals
- These display numeric literals that are integer and decimal.
+ Commands that affect the flow of control may accept postconditionals on
+ individual command arguments. Because multiple arguments act as multiple
+ commands, this is a straight-forward application of the same principal as
+ command postconditional. The only M standard commands that accept argument
+ postconditionals are DO, GOTO, and XECUTE. The GT.M command extensions
+ that accept argument postconditionals are BREAK, ZGOTO, and ZSYSTEM.
- M also accepts numeric literals in the form of a mantissa and an exponent,
- separated by a delimiter of "E" in uppercase. The mantissa may be an
- integer or a decimal fraction. The integer exponent may have an optional
- leading minus sign (-).
+3 Timeouts
+ Timeouts
- Example:
+ M provides timeouts as a tool to retain program control over commands of
+ indefinite duration. A timeout consists of a colon (:) delimiter on an
+ argument, followed by a numeric expression specifying the number of
+ seconds for M to attempt to execute the command. When the timeout is zero
+ (0), M makes a single attempt to complete the command.
- GTM>WRITE 8E6
- 8000000
- GTM> WRITE 8E-6
- .000008
- GTM>
+ GT.M has been designed to allow large timeout values, and to protect
+ against arithmetic overflow when converting large timeout values to
+ internal representations. When a command has a timeout, M maintains the
+ $TEST intrinsic special variable as the command completes. If the command
+ completes successfully, M sets $TEST to TRUE (1). If the command times out
+ before successful completion, M sets $TEST to FALSE (0). When a command
+ argument does not specify a timeout, M does not maintain $TEST.
- **Caution**
+ When a READ times out, M returns any characters that have arrived between
+ the start of the command and the timeout. M does not produce any partial
+ results for any of the other timed commands.
- The exponential numeric form may lead to ambiguities in the meaning of
- subscripts. Because numeric subscripts collate ahead of string subscripts,
- the string subscript "01E5" is not the same as the numeric subscript 01E5.
+2 M_Locks
+ M Locks
- GT.M handles numeric strings which are not canonical within the
- implementation as strings unless the application specifically requests
- they be treated as numbers. Any use in a context defined as numeric
- elicits numeric treatment; this includes operands of numeric operators,
- numeric literals, and some intrinsic function arguments. When the code
- creates a large number out of range , GT.M gives a NUMOFLOW error. When
- the code creates a small fractional number out of range GT.M treats it as
- zero (0). The GT.M number range is (to the limit of accuracy) 1E-43 to
- 1E47. When the application creates an in-range number that exceeds the
- GT.M numeric accuracy of 18 significant digits, GT.M silently retains the
- most significant digits. With standard collation, GT.M collates canonic
- numeric strings used as subscripts numerically, while it collates
- non-canonic numbers as strings.
+ The LOCK command reserves one or more resource names. Only one process at
+ a time can reserve a resource name. Resource names follow exactly the same
+ formation rules as M variables. They may be unsubscripted or subscripted
+ and may or may not have a leading caret (^) prefix. M code commonly uses
+ LOCKs as flags that control access to global data. Generally, a LOCK
+ specifies the resource with the same name as the global variable that
+ requires protected access. However, this is only a convention. LOCKing
+ does not keep two or more processes from modifying the same global
+ variable. It only keeps another process from LOCKing the same resource
+ name at the same time.
-2 Expressions
- Expressions
+ M LOCKs are hierarchical. If one process holds a LOCK on a resource, no
+ other process can LOCK either an ancestor or a descendant resource. For
+ example, a LOCK on ^A(1,2) blocks LOCKs on either ^A(1), or ^A(1,2,3), but
+ not on, for example, ^A(2) or its descendants.
- The following items are legal M expression atoms (expratom). An expression
- atom is a component of an M expression.
+ A LOCK argument may contain any subscripted or unsubscripted M variable
+ name including a name without a preceding caret symbol (^). As they have
+ the appearance of local variable names, resource names with no preceding
+ caret symbol (^) are commonly referred to as "local LOCKs" even though
+ these LOCKs interact with other processes.
- * Local variables
- * Global variables
- * Intrinsic special variables
- * Intrinsic functions
- * Extrinsic functions
- * Extrinsic special variables
- * Numeric literals
- * String literals
- * An expression enclosed in parentheses
- * Any of the above preceded by a unary operator
+2 Intrinsic_Functions
+ Intrinsic Functions
- In addition, any of these items may be combined with a binary operator and
- another expression atom.
+ M Intrinsic Functions start with a single dollar sign ($) and have one or
+ more arguments enclosed in parentheses () and separated by commas (,).
+ These functions provide an expression result by performing actions that
+ would be impossible or difficult to perform using M commands. It is now
+ possible to invoke a C function in a package via the external call
+ mechanism.
-2 Operators
- Operators
+2 Intrinsic_Special_Variables
+ Intrinsic Special Variables
- M has both unary and binary operators.
+ M Intrinsic Special Variables start with a single dollar sign ($). GT.M
+ provides such variables for program examination. In some cases, the
+ Intrinsic Special Variables may be SET to modify the corresponding part of
+ the environment.
-3 Precedence
- Precedence
+2 Routines
+ Routines
- All unary operations have right to left precedence.
+ M routines have a name and consist of lines of code followed by a
+ formfeed. M separates the name of a routine from the body of the routine
+ with an end-of-line which is a line-feed. This form is mostly used for
+ interchange with other M implementations and can be read and written by
+ the %RI and %RO utility routines.
- All M binary operations have strict left to right precedence. This
- includes all arithmetic, string, and logical operations. Hierarchies of
- operations require explicit establishment of precedence using parentheses
- (). Although this rule is counterintuitive, it is easy to remember and has
- no exceptions.
+ GT.M stores routine sources in UNIX text files.
-3 Arithmetic_Operators
- Arithmetic Operators
+ In M, a routine has no particular impact on variable management and may
+ include code that is invoked at different times and has no logical
+ intersection.
- All arithmetic operators force M to evaluate the expressions to which they
- apply as numeric. The arithmetic operators are:
+3 Lines
+ Lines
- + as a unary operator simply forces M to evaluate the expression following
- as numeric; as a binary operator it causes M to perform addition.
+ A line of M code consists of the following elements in the following
+ order:
- - as a unary operator causes M to negate the expression following; as a
- binary operator it causes M to perform subtraction.
+ * An optional label.
+ * A line-start delimiter. The standard defines the line-start delimiter
+ as a space (<SP>) character. In order to enhance routine readability,
+ GT.M extends M by accepting one or more tab (<HT>) characters as
+ line-start delimiters.
+ * Zero or more level indicators, which are periods (.). The level
+ indicators show the level of nesting for argumentless DO commands: the
+ more periods, the deeper the nesting. M ignores lines that contain
+ level indicators unless they directly follow an argumentless DO
+ command with a matching level of nesting.
+ * Zero or more commands and their arguments. M accepts multiple commands
+ on a line. The argument(s) of one command are separated from the next
+ command by a command-start delimiter, consisting of one or more spaces
+ (<SP>).
+ * A terminating end-of-line, which is a line feed.
- * binary operator for multiplication.
+4 Labels
+ Labels
- ** binary operator for exponentiation.
+ In addition to labels that follow the rules for M names, M accepts labels
+ consisting only of digits. In a label consisting only of digits, leading
+ zeros are considered significant. For example, labels 1 and 01 are
+ different. Formalists may immediately follow a label. A Formalists
+ consists of one or more names enclosed in parentheses (). Formalists
+ identify local variables that "receive" passed values in M parameter
+ passing. For more information, see "Parameter Passing".
- / binary operator for fractional division.
+ In GT.M, a colon (:) delimiter may be appended to the label, which causes
+ the label to be treated as "local." Within the routine in which they
+ appear, they perform exactly as they would without the trailing colon but
+ they are inaccessible to other routines. Using local labels reduces object
+ size and linking overhead, for both ZLINK and host linking.
- \ binary operator for integer division.
+4 Comments
+ Comments
- # binary operator for modulo, that is, causes M to produce the remainder
- from integer division of the first argument by the second.
+ In addition to commands, a line may also contain a comment that starts
+ with a leading semi-colon (;) delimiter. The scope of a comment is the
+ remainder of the line. In other words, M ignores anything to the right of
+ the comment delimiter. The standard defines the comment delimiter (;) as
+ it would a command, and therefore requires that it always appear after a
+ linestart. GT.M extends the standard to permit comments to start at the
+ first character of a line or in an argument position.
- Remember that precedence is left to right for all arithmetic operators.
+3 Entry_References
+ Entry References
- Example:
-
- GTM>WRITE 1+1
- 2
- GTM>WRITE 2-1
- 1
- GTM>WRITE 2*2
- 4
- GTM>WRITE 3**2
- 9
- GTM>WRITE 4/2
- 2
- GTM>WRITE 7
- 2
- GTM>WRITE 7#3
- 1
- GTM>
+ M entryrefs provide a generalized target for referring to a line within a
+ routine. An entryref may contain some combination of a label, an offset,
+ and a routine name (in that order). The offset is delimited by a plus sign
+ (+) and the routinename is delimited by a caret symbol(^). When an
+ entryref does not contain a label, M assumes the offset is from the
+ beginning of the routine. When an entryref does not contain an offset, M
+ uses an offset of zero (0). When an entryref does not contain a routine
+ name, M assumes the routine that is currently executing.
- This simple example demonstrates how each arithmetic binary operation uses
- numeric literals.
+ M permits every element in an entryref to have the form of an indirection
+ operator, followed by an element that evaluates to a legitimate occurrence
+ of that portion of the entryref.
- Example:
+ **Note**
- GTM>WRITE +"12ABC"
- 12
- GTM>WRITE --"-3-4"
- -3
- GTM>
+ While most commands and functions that use entryrefs permit argument
+ indirection, M does not accept indirection that resolves to a combination
+ of label and offset or offset and routine name.
- The first WRITE shows the unary plus sign (+) operation forcing the
- numeric evaluation of a string literal. The second WRITE demonstrates the
- unary minus sign (-). Note the second minus sign within the string literal
- does not cause subtraction, but rather, terminates the numeric evaluation
- with the result of negative three (-3). Each of the leading minus signs
- causes one negation and therefore, the result is negative three (-3).
+ Offsets provide an extremely useful tool for debugging. However, avoid
+ their use in production code because they generally produce maintenance
+ problems.
-3 Logical_Operators
- Logical Operators
+3 Label_References
+ Label References
- M logical operators always produce a result that is TRUE (1) or FALSE (0).
- All logical operators force M to evaluate the expressions to which they
- apply as truth-valued. The logical operators are:
+ M labelrefs are a subset of entryrefs that exclude offsets and separate
+ indirection. Labelrefs are used with parameter passing.
- ' unary NOT operator negates current truth-value; M accepts placement of
- the NOT operator next to a relational operator, for example, A'=B as
- meaning '(A=B).
+2 Indirection
+ Indirection
- &binary AND operator produces a true result only if both of the
- expressions are true.
+ M provides indirection as a means to defer definition of elements of the
+ code until run-time. Indirection names a variable that holds or "points"
+ to the element. The indirection operator is the "at" symbol (@).
- ! binary OR operator produces a true result if either of the expressions
- is true.
+3 Argument_Indirection
+ Argument Indirection
- Remember that precedence is always left to right, and that logical
- operators have the same precedence as all other operators.
+ Most commands accept indirection of their entire argument.
Example:
- GTM>WRITE '0
- 1
- GTM>WRITE '1
- 0
- GTM>WRITE '5689
- 0
- GTM>WRITE '-1
- 0
- GTM>WRITE '"ABC"
- 1
- GTM>
+ GTM>set x="^INDER"
+ GTM>do @x
- The above example demonstrates the unary NOT operation. Note that any
- non-zero numeric value is true and has a false negation.
+ This example is equivalent to do ^INDER.
+
+3 Atomic_Indirection
+ Atomic Indirection
+
+ Any expratom or any local or global variable name may be replaced by
+ indirection.
Example:
- GTM>WRITE 0&0
- 0
- GTM>WRITE 1&0
- 0
- GTM>WRITE 0&1
- 0
- GTM>WRITE 1&1
- 1
- GTM>WRITE 2&1
- 1
- GTM>WRITE 0!0
- 0
- GTM>WRITE 1!0
- 1
- GTM>WRITE 0!1
- 1
- GTM>WRITE 1!1
- 1
- GTM>WRITE 2!1
- 1
+ GTM>set x="HOOP",b="x"
+ GTM>write a="HULA "__ at b
+ HULA HOOP
GTM>
- The above example demonstrates all cases covered by the binary logical
- operators.
-
-3 String_Operators
- String Operators
+ This example uses indirection within a concatenation operation.
- All string operators force M to evaluate the expressions to which they
- apply as strings. The string operator is:
+3 Entryref_Indirection
+ Entryref Indirection
- _binary operator causes M to concatenate the second expression with the
- first expresion
+ Any element of an entryref may be replaced by indirection.
Example:
- GTM>WRITE "B"_"A"
- BA
- GTM>WRITE "A"_1
- A1
- GTM>
+ GTM>set lab="START",routine="PROG"
+ GTM>do @lab^@routine
- The above example demonstrates M concatenation.
+ This example is equivalent to do START^PROG.
-3 Numeric_Relational_Operators
- Numeric Relational Operators
+3 Pattern_Code_Indirection
+ Pattern Code Indirection
- M relational operators always generate a result of TRUE (1) or FALSE (0).
- All numeric relational operators force M to evaluate the expressions to
- which they apply as numeric. The numeric relational operators are:
+ A pattern code may be replaced by indirection.
- >binary arithmetic greater than
+ Example:
- <binary arithmetic less than
+ GTM>FOR p="1U.20A1"",""1U.20A",5N IF x?@p QUIT
+ GTM>ELSE WRITE !,"Incorrect format" QUIT
- The equal sign (=) does not force numeric evaluation, and should be viewed
- as a string operator. However, the equal sign between two numeric values
- tests for numeric equality.
+ This example uses pattern code indirection to test x for either a name or
+ a number.
- Other numeric relations are formed using the logical NOT operator
- apostrophe (') as follows:
+3 Name_Indirection
+ Name Indirection
- '> not greater than, that is, less than or equal to
+ Indirection may replace the prefix of a subscripted global or local
+ variable name. This "name" indirection requires two indirection operators,
+ a leading operator similar to the other forms of indirection, and a
+ trailing operator marking the transition to those subscripts that are not
+ specified by indirection.
- '< not less than, that is, greater than or equal to
+ Example:
- >= greater than or equal to, that is, not less than
+ GTM>SET from="B",to="^A(15),x=""
+ GTM>FOR SET x=$O(@from@(x)) Q:x="" S @to@(x)=@from@(x)
- <= less than or equal to, that is, not greater than
+ This example uses name indirection to copy the level contents of a local
+ array to a part of a global array. The example assumes that all existing
+ first level nodes of variable B have data.
- '= not equal, numeric or string operation
+3 Indirection_Concerns
+ Indirection Concerns
- Example:
+ M indirection provides a very powerful tool for allowing program
+ abstraction. However, because indirection is frequently unnecessary and
+ has some disadvantages, use it carefully.
- GTM>WRITE 1>2
- 0
- GTM>WRITE 1<2
- 1
- GTM>
+ Because routines that use indirection in some ways do not contain adequate
+ information for easy reading, such routines tend to be more difficult to
+ debug and maintain.
- The above example demonstrates the basic arithmetic relational operations.
+ To improve run-time performance, GT.M tends to move work from run-time to
+ compile-time. Indirection forces compiler actions to occur at run-time,
+ which minimizes the benefits of compilation.
- Example:
+ M allows most forms of indirection to be recursive. However, in real
+ applications, recursive indirection typically makes the code obscure and
+ slow.
- GTM>WRITE 1'<2
- 0
- GTM>WRITE 2'<1
- 1
- GTM>
+ There are circumstances where indirection serves a worthwhile purpose. For
+ instance, certain utility functions with a general nature may be clearly
+ abstracted and coded using indirection. Because M has no "CASE" command,
+ DO (or GOTO) with argument indirection provides a clear solution to the
+ problem of providing complex branching.
- The above example demonstrates combinations of arithmetic, relational
- operators with the logical NOT operator.
+ Some M users prototype with indirection and then replace indirection with
+ generated code that reduces run-time overhead. In any case, always
+ consider whether indirection can be replaced with a clearer or more
+ efficient approach.
-3 String_Relational_Operators
- String Relational Operators
+ Run-time errors from indirection or XECUTEs maintain $STATUS and $ZSTATUS
+ related information and cause normal error handling but do not provide
+ compiler supplied information on the location of any error within the code
+ fragment.
- M relational operators always generate a result of TRUE (1) or FALSE (0).
- All string relational operators force M to evaluate the expressions to
- which they apply as strings. The string relational operators are:
+2 Parameter_Passing
+ Parameter Passing
- = binary operator causes M to produce a TRUE if the expressions are equal.
+ Parameter passing provides a way of explicitly controlling some or all of
+ the variable context transferred between M routines.
- [ binary operator causes M to produce a TRUE if the first expression
- contains the ordered sequence of characters in the second expression.
+ M uses parameter passing for:
- ] binary operator causes M to produce a TRUE if the first expression
- lexically follows the second expression in the character encoding
- sequence, which by default is ASCII.
+ * A DO command with parameters
+ * Extrinsic functions and special variables
- ]] binary operator causes M to produce a TRUE if the first expression
- lexically sorts after the second expression in the subscript collation
- sequence.
+ Parameter passing is optional on DO commands.
- Note that all non-empty strings lexically follow the empty string, and
- every string contains the empty string.
+ Parameter passing uses two argument lists: the actuallist that specifies
+ the parameters that M passes to an invoked routine, and the formalist that
+ specifies the local variables to receive or associate with the parameters.
- Other string relations are formed using the logical NOT operator
- apostrophe (') as follows:
+3 Actuallists
+ Actuallists
- '[ does not contain.
+ An actuallist specifies the parameters M passes to the invoked routine.
+ The actuallist contains a list of zero or more parameters enclosed in
+ parentheses, immediately following a DO or extrinsic function.
- '] does not follow, that is, lexically less than or equal to.
-
- ']] does not sort after, that is, lexically less than or equal to in the
- subscript collation sequence.
+ An actuallist:
- '= not equal, numeric or string operation.
+ * Is made up of items separated by commas
+ * Contains expressions and/or actualnames. Items may be missing, that
+ is, two commas may appear next to each other, with nothing between
+ them.
+ * Must be used in an invocation of a label with a formallist, except in
+ the case of extrinsic special variables.
+ * Must not contain undefined variables.
+ * Must not have more items than a formallist with which it is used.
+ * May contain the same item in more than one position.
Example:
- GTM>WRITE "A"="B"
- 0
- GTM>WRITE "C"="C"
- 1
- GTM>WRITE "A"["B"
- 0
- GTM>WRITE "ABC"["C"
- 1
- GTM>WRITE "A"]"B"
- 0
- GTM>WRITE "B"]"A"
- 1
- GTM>WRITE "A"]]"B"
- 0
- GTM>WRITE "B"]]"A"
- 1
+ GTM>DO MULT(3,X,.RESULT)
- These examples demonstrate the string relational operators using string
- literals.
+3 Actualnames
+ Actualnames
- Example:
+ An actualname starts with a leading period (.) delimiter, followed by an
+ unsubscripted local variable name. Actualnames identify variables that are
+ passed by reference, as described in a subsequent section. While
+ expressions in an actualname are evaluated when control is transferred to
+ a formallabel, the variables identified by actualnames are not; therefore,
+ they do not need to be defined at the time control is transferred.
- GTM>WRITE 2]10
- 1
- GTM>WRITE 2]]10
- 0
- GTM>WRITE 0]"$"
- 1
- GTM>WRITE 0]]"$"
- 0
+3 Formallists
+ Formallists
- These examples illustrate that when using the primary ASCII character set,
- the main difference in the "follows" (]) operator and the "sorts-after"
- (]]) operator is the way they treat numbers.
+ A formallist specifies the variables M uses to hold passed values. A
+ formallist contains a list of zero or more parameters enclosed in
+ parentheses, immediately following a label.
Example:
- GTM>WRITE 1=1
- 1
- GTM>WRITE 1=2
- 0
- GTM>WRITE 1="1"
- 1
- GTM>WRITE 1=01
- 1
- GTM>WRITE 1="01"
- 0
- GTM>WRITE 1=+"01"
- 1
- GTM>
-
- These examples illustrate the dual nature of the equal sign operator. If
- both expressions are string or numeric, the results are straight forward.
- However, when the expressions are mixed, the native string data type
- prevails.
+ MULT(MP,MC,RES)
+ SET RES=MP*MC
+ QUIT RES
- Example:
+3 Formallabel
+ Formallabel
- GTM>WRITE "a"'="A"
- 1
- GTM>WRITE "FRED"'["RED"
- 0
- GTM>WRITE "ABC"']""
- 0
+ A label followed by a formallist is called a formallabel.
- These examples demonstrate combinations of the string relational operators
- with the NOT operator.
+3 Parameter_Passing_Operation
+ Parameter Passing Operation
-3 Pattern_Match_Operator
- Pattern Match Operator
+ M performs an implicit NEW on the formallist names and replaces the
+ formallist items with the actuallist items.
- The pattern match operator (?) causes M to return a TRUE if the expression
- ahead of the operator matches the characteristics described by the pattern
- following the operator. The pattern is not an expression.
+ M provides the actuallist values to the invoked procedure by giving each
+ element in the formallist the value or reference provided by the
+ corresponding element in the actuallist. M associates the first name in
+ the formallist with the first item in the actuallist, the second name in
+ the formallist with the second item in the actuallist and so on. If the
+ actuallist is shorter than the formallist, M ensures that the formallist
+ items with no corresponding value are in effect NEWed. If the formallist
+ item has no corresponding item in the actuallist (indicated by two
+ adjacent commas in the actuallist), that item in the formallist becomes
+ undefined.
- Patterns are made up of two elements:
+ If the actuallist item is an expression and the corresponding formallist
+ variable is an array, parameter passing does not affect the subscripted
+ elements of the array. If an actualname corresponds to a formallist
+ variable, M reflects array operations on the formallist variable, by
+ reference, in the variable specified by the actualname.
- 1. A repetition count
- 2. A pattern code, a string literal or an alternation list
+ M treats variables that are not part of the formallist as if parameter
+ passing did not exist (i.e., M makes them available to the invoked
+ routine).
- The element following the pattern match operator may consist of an
- indirection operator, followed by an element that evaluates to a
- legitimate pattern.
+ M initiates execution at the first command following the formallabel.
- The repetition count consists of either a single integer literal or a
- period (.) delimiter with optional leading and trailing integer literals.
- A single integer literal specifies an exact repetition count. The period
- syntax specifies a range of repetitions where the leading number is a
- minimum and the trailing number is a maximum. When the repetition count is
- missing the leading number, M assumes there is no minimum, (i.e., a
- minimum of zero). When the repetition count is missing the trailing
- number, M does not place a maximum on the number of repetitions.
+ A QUIT command terminates execution of the invoked routine. At the time of
+ the QUIT, M restores the formallist items to the values they had at the
+ invocation of the routine.
- The pattern codes are:
+ **Note**
- A alphabetic characters upper or lower case
+ In the case where a variable name appears as an actualname in the
+ actuallist, and also as a variable in the formallist, the restored value
+ reflects any change made by reference.
- C control characters ASCII 0-31 and 127
+ A QUIT from a DO does not take an argument, while a QUIT from an extrinsic
+ must have an argument. This represents one of the two major differences
+ between the DO command with parameters and the extrinsics. M returns the
+ value of the QUIT command argument as the value of the extrinsic function
+ or special variable. The other difference is that M stacks $TEST for
+ extrinsics.
- E any character; used to pass all characters in portions of the string
- where the pattern is not restricted
+ Example:
- L lower-case alphabetic characters, ASCII 97-122
+ SET X=30,Z="Hello"
+ DO WRTSQR(X)
+ ZWRITE
+ QUIT
+ WRTSQR(Z)
+ SET Z=Z*Z
+ WRITE Z,!
+ QUIT
- N digits 0-9, ASCII 48-57
+ Produces:
- P punctuation, ASCII 32-47, 58-64, 91-96, 123-126
+ 900
+ X=30
+ Z="Hello"
- U upper-case alphabetic characters, ASCII 65-90
+3 Parameter_Passing_Mechanisms
+ Parameter Passing Mechanisms
- Pattern codes may be upper or lower case and may be replaced with a string
- literal. GT.M allows the M pattern match definition of patcodes A, C, N,
- U, L, and P to be extended or changed, (A can only be modified implicitly
- by modifying L or U) and new patcodes added. For detailed information on
- enabling this functionality, refer to the "Internationalization" chapter
- in the GT.M Programmer's Guide.
+ M passes the actuallist values to the invoked routine using two
+ parameter-passing mechanisms:
- **Note**
+ * Call-by-Value - where expressions appear
+ * Call-by-Reference - where actualnames appear
- The GT.M compiler accepts pattern codes other than those explicitly
- defined above. If, at run-time, the pattern codes come into use and no
- pattern definitions are available, GT.M issues a run-time error
- (PATNOTFOUND). GT.M does not currently implement a mechanism for Y and Z
- patterns and continues to treat those as compile-time syntax errors.
+ A call-by-value passes a copy of the value of the actuallist expression to
+ the invoked routine by assigning the copy to a formallist variable. If the
+ parameter is a variable, the invoked routine may change that variable.
+ However, because M constructs that variable to hold the copy, it deletes
+ the variable holding the copy when the QUIT restores the prior formallist
+ values. This also means that changes to the variable by the invoked
+ routine do not affect the value of the variable in the invoking routine.
Example:
- GTM>WRITE "ABC"?3U
- 1
- GTM>WRITE "123-45-6789"?3N1"-"2N1"-"4N
- 1
+ SET X=30
+ DO SQR(X)
+ ZWRITE
+ QUIT
+ SQR(Z)SET Z=Z*Z
+ QUIT
- The first WRITE has a simple one-element pattern while the second has
- multiple elements including both codes and string literals. All the
- repetition counts are fixed.
+ Produces:
- Example:
+ X=30
- I x?.E1C.E W !,"Must not contain a control character" Q
+ A period followed by a name identifies an actualname and causes a
+ call-by-reference.
- This example uses a pattern match to test for control characters.
+ A call-by-reference passes a pointer to the variable of the invoked
+ routine so operations on the assigned formallist variable also act on the
+ actualname variable. Changes, including KILLs to the formallist variable,
+ immediately have the same affect on the corresponding actualname variable.
+ This means that M passes changes to formallist variables in the invoked
+ routine back to the invoking routine as changes in actualname variables.
Example:
- I acn?1U.20A1","1U.10A D
- .S acn=$G((^ACX($P(acn,","),$P(acn,",",2)))
+ SET X=30
+ DO SQR(.X)
+ ZWRITE
+ QUIT
+ SQR(Z)SET Z=Z*Z
+ QUIT
- This example uses a pattern match with implicit minimums to determine that
- an "account number" is actually a name, and to trigger a look-up of the
- corresponding account number in the ^ACX cross index.
+ Produces:
- The pattern match operator accepts the alteration syntax. Alteration
- consists of a repeat count followed by a comma-delimited list of patatoms
- enclosed in parentheses "()". The semantic is that the pattern matches if
- any of the listed patterns matches the operand string. For example,
- ?1(2N1"-"7N,3N1"-"2N1"-"4N).1U might be a way to match either a social
- security number or a taxpayer ID. Since alternation is defined as one of
- the ways of constructing a patatom, alternation can nest (be used
- recursively).
+ X=900
- **Note**
+3 Parameter_Passing_Extensions
+ Parameter Passing Extensions
- Complex pattern matches may not be efficient to evaluate, so every effort
- should be made to simplify any commonly used pattern and to determine if
- more efficient alternative logic would be more appropriate.
+ The standard does not provide for indirection of a labelref because the
+ syntax has an ambiguity.
-2 Commands
- Commands
+ Example:
- M commands may be abbreviated to a defined prefix. Most commands have
- arguments. However, some commands have either optional arguments or no
- arguments. When a command has no argument and is followed by more commands
- on the same line, at least two spaces (<SP>) must follow the command
- without arguments. Commands that accept arguments generally accept
- multiple arguments on the same command. M treats multiple arguments the
- same as multiple occurrences of the same command, each with its own
- argument.
-
-3 Postconditionals
- Postconditionals
-
- M provides postconditionals as a tool for placing a condition on the
- execution of a single command and, in some cases, a single command
- argument. A postconditional consists of a colon (:) delimiter followed by
- a truth-valued expression. When the expression evaluates to true, M
- executes the command occurrence. When the expression evaluates to false, M
- does not execute the command occurrence.
-
-4 Command_Postconditionals
- Command Postconditionals
-
- Command postconditionals appear immediately following a command and apply
- to all arguments for the command when it has multiple arguments. All
- commands except commands that themselves have a conditional aspect accept
- a command postconditional. Among the M standard commands, ELSE, FOR, and
- IF do not accept command postconditionals. All the GT.M command extensions
- accept command postconditionals.
+ DO @X(1)
-4 Argument_Postconditionals
- Argument Postconditionals
+ This example could be:
- Commands that affect the flow of control may accept postconditionals on
- individual command arguments. Because multiple arguments act as multiple
- commands, this is a straight-forward application of the same principal as
- command postconditional. The only M standard commands that accept argument
- postconditionals are DO, GOTO, and XECUTE. The GT.M command extensions
- that accept argument postconditionals are BREAK, ZGOTO, and ZSYSTEM.
+ * An invocation of the label specified by X with a parameter of 1.
+ * An invocation of the label specified by X(1) with no parameter list.
-3 Timeouts
- Timeouts
+ GT.M processes the latter interpretation as illustrated in the following
+ example.
- M provides timeouts as a tool to retain program control over commands of
- indefinite duration. A timeout consists of a colon (:) delimiter on an
- argument, followed by a numeric expression specifying the number of
- seconds for M to attempt to execute the command. When the timeout is zero
- (0), M makes a single attempt to complete the command.
+ Example:
- GT.M has been designed to allow large timeout values, and to protect
- against arithmetic overflow when converting large timeout values to
- internal representations. When a command has a timeout, M maintains the
- $TEST intrinsic special variable as the command completes. If the command
- completes successfully, M sets $TEST to TRUE (1). If the command times out
- before successful completion, M sets $TEST to FALSE (0). When a command
- argument does not specify a timeout, M does not maintain $TEST.
+ The syntax:
- When a READ times out, M returns any characters that have arrived between
- the start of the command and the timeout. M does not produce any partial
- results for any of the other timed commands.
+ SET A(1)="CUBE",X=5
+ DO @A(1)(.X)
+ WRITE X,!
+ QUIT
+ CUBE(C);cube a variable
+ SET C=C*C*C
+ QUIT
-2 M_Locks
- M Locks
+ Produces the result:
- The LOCK command reserves one or more resource names. Only one process at
- a time can reserve a resource name. Resource names follow exactly the same
- formation rules as M variables. They may be unsubscripted or subscripted
- and may or may not have a leading caret (^) prefix. M code commonly uses
- LOCKs as flags that control access to global data. Generally, a LOCK
- specifies the resource with the same name as the global variable that
- requires protected access. However, this is only a convention. LOCKing
- does not keep two or more processes from modifying the same global
- variable. It only keeps another process from LOCKing the same resource
- name at the same time.
+ 125
- M LOCKs are hierarchical. If one process holds a LOCK on a resource, no
- other process can LOCK either an ancestor or a descendant resource. For
- example, a LOCK on ^A(1,2) blocks LOCKs on either ^A(1), or ^A(1,2,3), but
- not on, for example, ^A(2) or its descendants.
+ GT.M follows analogous syntax for routine indirection:
- A LOCK argument may contain any subscripted or unsubscripted M variable
- name including a name without a preceding caret symbol (^). As they have
- the appearance of local variable names, resource names with no preceding
- caret symbol (^) are commonly referred to as "local LOCKs" even though
- these LOCKs interact with other processes.
+ DO ^@X(A) invokes the routine specified by X(A).
-2 Intrinsic_Functions
- Intrinsic Functions
+ DO ^@(X)(A) invokes the routine specified by X and passes the parameter A.
- M Intrinsic Functions start with a single dollar sign ($) and have one or
- more arguments enclosed in parentheses () and separated by commas (,).
- These functions provide an expression result by performing actions that
- would be impossible or difficult to perform using M commands. It is now
- possible to invoke a C function in a package via the external call
- mechanism.
+ DO ^@X(A)(A) invokes the routine specified by X(A) and passes the
+ parameter A.
-2 Intrinsic_Special_Variables
- Intrinsic Special Variables
+2 External_Calls
+ External Calls
- M Intrinsic Special Variables start with a single dollar sign ($). GT.M
- provides such variables for program examination. In some cases, the
- Intrinsic Special Variables may be SET to modify the corresponding part of
- the environment.
+ GT.M allows references to a GT.M database from programs written in other
+ programming languages that run under UNIX.
-2 Routines
- Routines
+ In GT.M, calls to C language routines may be made with the following
+ syntax:
- M routines have a name and consist of lines of code followed by an
- end-of-record which is a carriage return, formfeed (<CR><FF>) sequence. M
- separates the name of a routine from the body of the routine with an
- end-of-line which is a carriage-return, line-feed (<CR><LF>) sequence.
+ DO &[packagename.]name[^name][parameter-list]
- GT.M stores routine sources in RMS UNIX files and implicitly supplies the
- end-of-record and end-of-line character sequences.
+ or as an expression element,
- In M, a routine has no particular impact on variable management and may
- include code that is invoked at different times and has no logical
- intersection.
+ $&[packagename.]name[^name][parameter-list]
-3 Lines
- Lines
+ Where packagename, like the name elements is a valid M name. Because of
+ the parsing conventions of M, the identifier between the ampersand (&) and
+ the optional parameter-list has precisely constrained punctuation - a
+ later section describes how to transform this into a more richly
+ punctuated name should that be appropriate for the called function. While
+ the intent of the syntax is to permit the name^name to match an M
+ labelref, there is no semantic implication to any use of the caret (^).
- A line of M code consists of the following elements in the following
- order:
+ **Note**
- * An optional label.
- * A line-start delimiter. The standard defines the line-start delimiter
- as a space (<SP>) character. In order to enhance routine readability,
- GT.M extends M by accepting one or more tab (<HT>) characters as
- line-start delimiters.
- * Zero or more level indicators, which are periods (.). The level
- indicators show the level of nesting for argumentless DO commands: the
- more periods, the deeper the nesting. M ignores lines that contain
- level indicators unless they directly follow an argumentless DO
- command with a matching level of nesting.
- * Zero or more commands and their arguments. M accepts multiple commands
- on a line. The argument(s) of one command are separated from the next
- command by a command-start delimiter, consisting of one or more spaces
- (<SP>).
- * A terminating end-of-line, which is a carriage return, line feed
- (<CR><LF>) sequence.
+ For more information on external calls, see Chapter 11: "Integrate
+ External".
-4 Labels
- Labels
+2 Extrinsic_Functions
+ Extrinsic Functions
- In addition to labels that follow the rules for M names, M accepts labels
- consisting only of digits. In a label consisting only of digits, leading
- zeros are considered significant. For example, labels 1 and 01 are
- different. Formalists may immediately follow a label. A Formalists
- consists of one or more names enclosed in parentheses (). Formalists
- identify local variables that "receive" passed values in M parameter
- passing. For more information, see "Parameter Passing".
+ An extrinsic function is an M subroutine that another M routine can invoke
+ to return a value.
- In GT.M, a colon (:) delimiter may be appended to the label, which causes
- the label to be treated as "local." Within the routine in which they
- appear, they perform exactly as they would without the trailing colon but
- they are inaccessible to other routines. Using local labels reduces object
- size and linking overhead, for both ZLINK and host linking.
+ The format for extrinsic functions is:
-4 Comments
- Comments
+ $$[label][^routinename]([expr|.lname[,...]])
- In addition to commands, a line may also contain a comment that starts
- with a leading semi-colon (;) delimiter. The scope of a comment is the
- remainder of the line. In other words, M ignores anything to the right of
- the comment delimiter. The standard defines the comment delimiter (;) as
- it would a command, and therefore requires that it always appear after a
- linestart. GT.M extends the standard to permit comments to start at the
- first character of a line or in an argument position.
+ M stacks $TEST for extrinsic functions. This is one of the two major
+ differences between the DO command with parameters and extrinsics. On
+ return from an extrinsic function, M restores the value of $TEST to what
+ it was before the extrinsic function, regardless of the actions executed
+ by the invoked routine.
-3 Entry_References
- Entry References
+ M requires a routine that implements an extrinsic function to terminate
+ with an explicit QUIT command which has an argument. M returns the value
+ of the QUIT command argument as the value of the extrinsic function. This
+ is the other major difference between the DO command with parameters and
+ extrinsics. It is now possible to invoke a C function in a package via the
+ external call mechanism.
- M entryrefs provide a generalized target for referring to a line within a
- routine. An entryref may contain some combination of a label, an offset,
- and a routine name (in that order). The offset is delimited by a plus sign
- (+) and the routinename is delimited by a caret symbol(^). When an
- entryref does not contain a label, M assumes the offset is from the
- beginning of the routine. When an entryref does not contain an offset, M
- uses an offset of zero (0). When an entryref does not contain a routine
- name, M assumes the routine that is currently executing.
+ Example:
- M permits every element in an entryref to have the form of an indirection
- operator, followed by an element that evaluates to a legitimate occurrence
- of that portion of the entryref.
+ POWER(V,X,S,T);extrinsic to raise to a power
+ ;ignores fractional powers
+ SET T=1,S=0
+ IF X<0 SET X=-X,S=1
+ FOR X=1:1:X S T=T*V
+ QUIT $S(S:1/T,1:T)
+ GTM> WRITE $$^POWER(3,4)
+ 81
+ GTM>
**Note**
- While most commands and functions that use entryrefs permit argument
- indirection, M does not accept indirection that resolves to a combination
- of label and offset or offset and routine name.
-
- Offsets provide an extremely useful tool for debugging. However, avoid
- their use in production code because they generally produce maintenance
- problems.
+ The POWER routine uses a formallist that is longer than the "expected"
+ actuallist to protect local working variables. Such practice may be
+ encouraged or discouraged by your institution's standards.
-3 Label_References
- Label References
+2 Extrinsic_Special_Variables
+ Extrinsic Special Variables
- M labelrefs are a subset of entryrefs that exclude offsets and separate
- indirection. Labelrefs are used with parameter passing.
+ An extrinsic special variable is a user-written M subroutine that another
+ M routine can invoke to return a value.
-2 Indirection
- Indirection
+ The format for extrinsic special variables is:
- M provides indirection as a means to defer definition of elements of the
- code until run-time. Indirection names a variable that holds or "points"
- to the element. The indirection operator is the "at" symbol (@).
+ $$[label][^routinename]
-3 Argument_Indirection
- Argument Indirection
+ An extrinsic special variable can be thought of as an extrinsic function
+ without input parameters. $$x is equivalent in operation to $$x().
+ Extrinsic special variables are the only case where invocation of a
+ formallabel does not require an actuallist. M stacks $TEST for extrinsic
+ special variables.
- Most commands accept indirection of their entire argument.
+ M requires that a routine that implements an extrinsic special variable
+ terminate with an explicit QUIT command which has an argument. M returns
+ the value of the QUIT command argument as the value of the extrinsic
+ special variable.
Example:
- GTM>set x="^INDER"
- GTM>do @x
+ GTM>ZPRINT ^DAYOWEEK
+ DAYOWEEK();extrinsic special variable to
+ ;provide the day of the week
+ QUIT $ZD($H,"DAY")
+ GTM>WRITE $$DAYOWEEK^DAYOWEEK
+ MON
- This example is equivalent to do ^INDER.
+2 Transaction_Processing
+ Transaction Processing
-3 Atomic_Indirection
- Atomic Indirection
+ Transaction Processing (TP) provides a way for M programs to organize
+ database updates into logical groups that occur as a single event (i.e.,
+ either all the database updates in a transaction occur, or none of them
+ occur). No other process may behave as if it observed any intermediate
+ state.
- Any expratom or any local or global variable name may be replaced by
- indirection.
+ Transaction processing has been designed to improve output and eliminate
+ "live lock" conditions. The number of attempts to complete the transaction
+ is limited to four. The fourth attempt is made inside a "critical section"
+ with all other processes temporarily locked out of the database. Between
+ the second and third tries, GT.M waits for a random interval between 0 and
+ 500 milliseconds.
- Example:
+3 TP_Definitions
+ TP Definitions
- GTM>set x="HOOP",b="x"
- GTM>write a="HULA "__ at b
- HULA HOOP
- GTM>
+ In M, a transaction is a sequence of commands that begins with a TSTART
+ command, ends with a TCOMMIT command, and is not within the scope of
+ another transaction.
- This example uses indirection within a concatenation operation.
+ A successful transaction ends with a COMMIT that is triggered by the
+ TCOMMIT command at the end of the transaction. A COMMIT causes all the
+ database updates performed within the transaction to become available to
+ other processes.
-3 Entryref_Indirection
- Entryref Indirection
+ An unsuccessful transaction ends with a ROLLBACK. ROLLBACK is invoked
+ explicitly by the TROLLBACK command, or implicitly at a process
+ termination that occurs during a transaction in progress. An error within
+ a transaction does not cause an implicit ROLLBACK. A ROLLBACK removes any
+ database updates performed within the transaction before they are made
+ available to other processes. ROLLBACK also releases all resources LOCKed
+ since the start of the transaction, and makes the naked reference
+ undefined.
- Any element of an entryref may be replaced by indirection.
+ A RESTART is a transfer of control to the TSTART at the beginning of the
+ transaction. RESTART implicitly includes a ROLLBACK and may optionally
+ restore local variables to the values they had when the initial TSTART was
+ originally executed. A RESTART always restores $TEST and the naked
+ reference to the values they had when the initial TSTART was executed.
+ RESTART does not manage device state information. A RESTART is invoked by
+ the TRESTART command or by M if it is determined that the transaction is
+ in conflict with other database updates. RESTART can only successfully
+ occur if the initial TSTART includes an argument that enables RESTART.
- Example:
+3 TP_Performance
+ TP Performance
- GTM>set lab="START",routine="PROG"
- GTM>do @lab^@routine
+ To achieve the best GT.M performance, transactions should:
- This example is equivalent to do START^PROG.
+ * be as short as possible
+ * consist, as much as possible, only of global updates
+ * be SERIAL with no associated LOCKs
+ * have RESTART enabled with a minimum of local variables protected by a
+ restart portion of the TSTART argument.
+ * Large concurrent transactions using TCOMMIT may result in repeated and
+ inefficient attempts by competing processes to capture needed scarce
+ resources, resulting in poor performance.
-3 Pattern_Code_Indirection
- Pattern Code Indirection
+ Example:
- A pattern code may be replaced by indirection.
+ TSTART ():SERIAL
+ SET (ACCT,^M(0))=^M(0)+1
+ SET ^M(ACCT)=PREC,^PN(NAM)=ACCT
+ TCOMMIT
Example:
- GTM>FOR p="1U.20A1"",""1U.20A",5N IF x?@p QUIT
- GTM>ELSE WRITE !,"Incorrect format" QUIT
-
- This example uses pattern code indirection to test x for either a name or
- a number.
+ TSTART ():SERIAL
+ IF $TRESTART>3 DO QUIT
+ .TROLLBACK
+ .WRITE !,"Too many RESTARTs"
+ .QUIT
+ SET (NEXT,^ID(0))=^ID(0)+1
+ SET ^ID(NEXT)=RECORD,^XID(ZIP,NEXT)=""
+ TCOMMIT
-3 Name_Indirection
- Name Indirection
+1 Commands
+ Commands
- Indirection may replace the prefix of a subscripted global or local
- variable name. This "name" indirection requires two indirection operators,
- a leading operator similar to the other forms of indirection, and a
- trailing operator marking the transition to those subscripts that are not
- specified by indirection.
+ This chapter describes M language commands implemented in GT.M. All
+ commands starting with the letter Z are GT.M additions to the ANSI
+ standard command set. The M standard specifies standard abbreviations for
+ commands and rejects any non-standard abbreviation.
- Example:
+2 Break
+ Break
- GTM>SET from="B",to="^A(15),x=""
- GTM>FOR SET x=$O(@from@(x)) Q:x="" S @to@(x)=@from@(x)
+ The BREAK command pauses execution of the code and initiates Direct Mode.
- This example uses name indirection to copy the level contents of a local
- array to a part of a global array. The example assumes that all existing
- first level nodes of variable B have data.
+ The format of the BREAK command is:
-3 Indirection_Concerns
- Indirection Concerns
+ B[REAK][:tvexpr] [expr[:tvexpr][,...]]
- M indirection provides a very powerful tool for allowing program
- abstraction. However, because indirection is frequently unnecessary and
- has some disadvantages, use it carefully.
+ Issuing a BREAK command inside an M transaction destroys the Isolation of
+ that transaction. Because of the way that GT.M implements transaction
+ processing, a BREAK within a transaction may cause the transaction to
+ suffer an indefinite number of restarts ("live lock").
- Because routines that use indirection in some ways do not contain adequate
- information for easy reading, such routines tend to be more difficult to
- debug and maintain.
+ ZCONTINUE resumes execution of the interrupted program.
- To improve run-time performance, GT.M tends to move work from run-time to
- compile-time. Indirection forces compiler actions to occur at run-time,
- which minimizes the benefits of compilation.
+ The VIEW "BREAKMSG" mask selectively enables or disables these messages.
+ By default, a process executing a GT.M image displays all BREAK messages.
- M allows most forms of indirection to be recursive. However, in real
- applications, recursive indirection typically makes the code obscure and
- slow.
+3 Examples
+ Examples
- There are circumstances where indirection serves a worthwhile purpose. For
- instance, certain utility functions with a general nature may be clearly
- abstracted and coded using indirection. Because M has no "CASE" command,
- DO (or GOTO) with argument indirection provides a clear solution to the
- problem of providing complex branching.
+ Example:
- Some M users prototype with indirection and then replace indirection with
- generated code that reduces run-time overhead. In any case, always
- consider whether indirection can be replaced with a clearer or more
- efficient approach.
+ LOOP0 F S act=$O(^act(act)) Q:act="" B:debug D LOOP1
- Run-time errors from indirection or XECUTEs maintain $STATUS and $ZSTATUS
- related information and cause normal error handling but do not provide
- compiler supplied information on the location of any error within the code
- fragment.
+ This FOR loop contains a BREAK with a command postconditional.
-2 Parameter_Passing
- Parameter Passing
+ Example:
- Parameter passing provides a way of explicitly controlling some or all of
- the variable context transferred between M routines.
+ GTM>ZPRINT ^br
+ br;
+ kill
+ for i=1:1:3 do break;
+ quit
+ break;
+ write "Iteration ",i,?15,"x=",$get(x,"<UNDEF>"),!
+ break:$data(x) "write ""OK"",!":x,"write ""Wrong again"",!":'x
+ set x=$increment(x,$data(x))
+ quit
+ GTM>DO ^br
+ Iteration 1 x=<UNDEF>
+ Iteration 2 x=0
+ %GTM-I-BREAK, Break instruction encountered
+ At M source location break+2^br
+ GTM>ZCONTINUE
+ Wrong again
+ %GTM-I-BREAK, Break instruction encountered
+ At M source location break+2^br
- M uses parameter passing for:
+ GTM>ZCONTINUE
+ Iteration 3 x=1
+ OK
+ %GTM-I-BREAK, Break instruction encountered
+ At M source location break+2^br
- * A DO command with parameters
- * Extrinsic functions and special variables
+ GTM>ZCONTINUE
+ %GTM-I-BREAK, Break instruction encountered
+ At M source location break+2^br
- Parameter passing is optional on DO commands.
+ GTM>ZCONTINUE
- Parameter passing uses two argument lists: the actuallist that specifies
- the parameters that M passes to an invoked routine, and the formalist that
- specifies the local variables to receive or associate with the parameters.
+ GTM>
-3 Actuallists
- Actuallists
+ This uses a BREAK with both command and argument postconditionals. The
+ actions display debugging messages.
- An actuallist specifies the parameters M passes to the invoked routine.
- The actuallist contains a list of zero or more parameters enclosed in
- parentheses, immediately following a DO or extrinsic function.
+2 Close
+ Close
- An actuallist:
+ The CLOSE command breaks the connection between a process and a device.
- * Is made up of items separated by commas
- * Contains expressions and/or actualnames. Items may be missing, that
- is, two commas may appear next to each other, with nothing between
- them.
- * Must be used in an invocation of a label with a formallist, except in
- the case of extrinsic special variables.
- * Must not contain undefined variables.
- * Must not have more items than a formallist with which it is used.
- * May contain the same item in more than one position.
+ The format of the CLOSE command is:
- Example:
+ C[LOSE][:tvexpr] expr[:(keyword[=expr][:...])][,...]
- GTM>DO MULT(3,X,.RESULT)
+2 Do
+ Do
-3 Actualnames
- Actualnames
+ The DO command makes an entry in the GT.M invocation stack and transfers
+ execution to the location specified by the entryref.
- An actualname starts with a leading period (.) delimiter, followed by an
- unsubscripted local variable name. Actualnames identify variables that are
- passed by reference, as described in a subsequent section. While
- expressions in an actualname are evaluated when control is transferred to
- a formallabel, the variables identified by actualnames are not; therefore,
- they do not need to be defined at the time control is transferred.
+ The format of the DO command is:
-3 Formallists
- Formallists
+ D[O][:tvexpr] [entryref[(expr|.lvn[,...])][:tvexpr][,...]]
- A formallist specifies the variables M uses to hold passed values. A
- formallist contains a list of zero or more parameters enclosed in
- parentheses, immediately following a label.
+3 Examples
+ Examples
Example:
- MULT(MP,MC,RES)
- SET RES=MP*MC
- QUIT RES
-
-3 Formallabel
- Formallabel
+ GTM>DO ^%RD
- A label followed by a formallist is called a formallabel.
+ This example invokes the routine directory utility program (%RD) from
+ Direct Mode. The caret symbol (^) specifies that the DO command invokes
+ %RD as an external routine.
-3 Parameter_Passing_Operation
- Parameter Passing Operation
+ Example:
- M performs an implicit NEW on the formallist names and replaces the
- formallist items with the actuallist items.
+ GTM>DO A(3)
- M provides the actuallist values to the invoked procedure by giving each
- element in the formallist the value or reference provided by the
- corresponding element in the actuallist. M associates the first name in
- the formallist with the first item in the actuallist, the second name in
- the formallist with the second item in the actuallist and so on. If the
- actuallist is shorter than the formallist, M ensures that the formallist
- items with no corresponding value are in effect NEWed. If the formallist
- item has no corresponding item in the actuallist (indicated by two
- adjacent commas in the actuallist), that item in the formallist becomes
- undefined.
-
- If the actuallist item is an expression and the corresponding formallist
- variable is an array, parameter passing does not affect the subscripted
- elements of the array. If an actualname corresponds to a formallist
- variable, M reflects array operations on the formallist variable, by
- reference, in the variable specified by the actualname.
-
- M treats variables that are not part of the formallist as if parameter
- passing did not exist (i.e., M makes them available to the invoked
- routine).
+ This example invokes the subroutine at label A and passes the value 3 as a
+ parameter. The DO argument does not have a caret symbol (^), therefore, it
+ identifies A as a label in the current routine.
- M initiates execution at the first command following the formallabel.
+ Example:
- A QUIT command terminates execution of the invoked routine. At the time of
- the QUIT, M restores the formallist items to the values they had at the
- invocation of the routine.
+ ReportA ; Label for ReportA
+ SET di="" OPEN outfile USE outfile
+ FOR SET di=$ORDER(^div(di)) QUIT:di="" DO PREP DO DO POST
+ .SET de="",(nr,gr)=0
+ .WRITE "Division ",di,! F S de=$ORDER(^de(di,de)) QUIT:de="" DO
+ ..WRITE "Department ",de," Gross Rev: ",^grev(di,de),!
+ ..WRITE "Department ",de," Net Rev: ",^nrev(di,de),!
+ ..SET gr=gr+^grev(di,de),nr=nr+^nrev(di,de)
+ .W "Division Gross Rev: ",gr,!,"Division Net Rev: ",nr,!
+ DO PRINT^OUTPUT(outfile)
+ QUIT
- **Note**
+ Example:
- In the case where a variable name appears as an actualname in the
- actuallist, and also as a variable in the formallist, the restored value
- reflects any change made by reference.
+ GTM>zprint ^SQR
+ SQR(z);
+ set revert=0
+ if $view("undef") set revert=1 view "noundef"
+ if z="" write "Missing parameter.",! view:revert "undef" quit
+ else write z*z,! view:revert "undef" quit
- A QUIT from a DO does not take an argument, while a QUIT from an extrinsic
- must have an argument. This represents one of the two major differences
- between the DO command with parameters and the extrinsics. M returns the
- value of the QUIT command argument as the value of the extrinsic function
- or special variable. The other difference is that M stacks $TEST for
- extrinsics.
+ GTM>do ^SQR(10)
+ 100
- Example:
+ GTM>do ^SQR
+ Missing parameter.
- SET X=30,Z="Hello"
- DO WRTSQR(X)
- ZWRITE
- QUIT
- WRTSQR(Z)
- SET Z=Z*Z
- WRITE Z,!
- QUIT
+ This examples demonstrates label invocations using DO with and without
+ parentheses.
- Produces:
+2 Else
+ Else
- 900
- X=30
- Z="Hello"
+ ELSE executes the remainder of the line after the ELSE if $TEST is FALSE
+ (0). GT.M does not execute the rest of the line if $TEST is TRUE (1).
-3 Parameter_Passing_Mechanisms
- Parameter Passing Mechanisms
+ The format of the ELSE command is:
- M passes the actuallist values to the invoked routine using two
- parameter-passing mechanisms:
+ E[LSE]
- * Call-by-Value - where expressions appear
- * Call-by-Reference - where actualnames appear
+ ELSE is analogous to IF '$TEST, except the latter statement switches $TEST
+ to its complement and ELSE never alters $TEST.
- A call-by-value passes a copy of the value of the actuallist expression to
- the invoked routine by assigning the copy to a formallist variable. If the
- parameter is a variable, the invoked routine may change that variable.
- However, because M constructs that variable to hold the copy, it deletes
- the variable holding the copy when the QUIT restores the prior formallist
- values. This also means that changes to the variable by the invoked
- routine do not affect the value of the variable in the invoking routine.
+3 Examples
+ Examples
Example:
- SET X=30
- DO SQR(X)
- ZWRITE
- QUIT
- SQR(Z)SET Z=Z*Z
- QUIT
+ If x=+x Set x=x+y
+ Else Write !,x
- Produces:
+ The IF command evaluates the conditional expression x=+x and sets $TEST.
+ If $TEST=1 (TRUE), GT.M executes the commands following the IF. The ELSE
+ on the following line specifies an alternative action to take if the
+ expression is false.
- X=30
+ Example:
- A period followed by a name identifies an actualname and causes a
- call-by-reference.
+ If x=+x Do ^GOFISH
+ Else Set x=x_"^"_y
- A call-by-reference passes a pointer to the variable of the invoked
- routine so operations on the assigned formallist variable also act on the
- actualname variable. Changes, including KILLs to the formallist variable,
- immediately have the same affect on the corresponding actualname variable.
- This means that M passes changes to formallist variables in the invoked
- routine back to the invoking routine as changes in actualname variables.
+ The DO with an argument after the IF raises the possibility that the
+ routine ^GOFISH changes the value of $TEST, thus making it possible to
+ execute both the commands following the IF and the commands following the
+ ELSE.
Example:
- SET X=30
- DO SQR(.X)
- ZWRITE
- QUIT
- SQR(Z)SET Z=Z*Z
- QUIT
+ Open dev::0 Else Write !,"Device unavailable" QUIT
- Produces:
+ This ELSE depends on the result of the timeout on the OPEN command. If the
+ OPEN succeeds, it sets $TEST to one (1) and GT.M skips the rest of the
+ line after the ELSE. If the OPEN fails, it sets $TEST to zero (0), and
+ GT.M executes the remainder of the line after the ELSE.
- X=900
+2 For
+ For
-3 Parameter_Passing_Extensions
- Parameter Passing Extensions
+ The FOR command provides a looping mechanism in GT.M. FOR does not
+ generate an additional level in the M standard stack model.
- The standard does not provide for indirection of a labelref because the
- syntax has an ambiguity.
+ The format of the FOR command is:
- Example:
+ F[OR][lvn=expr[:numexpr1[:numexpr2]][,...]]]
- DO @X(1)
+3 Examples
+ Examples
- This example could be:
+ Example:
- * An invocation of the label specified by X with a parameter of 1.
- * An invocation of the label specified by X(1) with no parameter list.
+ GTM>Kill i For i=1:1:5 Write !,i
+ 1
+ 2
+ 3
+ 4
+ 5
+ GTM>Write i
+ 5
+ GTM>
- GT.M processes the latter interpretation as illustrated in the following
- example.
+ This FOR loop has a control variable, i, which has the value one (1) on
+ the first iteration, then the value two (2), and so on, until in the last
+ iteration i has the value five (5). The FOR terminates because
+ incrementing i would cause it to exceed the limit. Notice that i is not
+ incremented beyond the limit.
Example:
- The syntax:
+ GTM>FOR x="hello",2,"goodbye" WRITE !,x
+ hello
+ 2
+ goodbye
+ GTM>
- SET A(1)="CUBE",X=5
- DO @A(1)(.X)
- WRITE X,!
- QUIT
- CUBE(C);cube a variable
- SET C=C*C*C
- QUIT
+ This FOR loop uses the control variable x and a series of arguments that
+ have no increments or limits. Notice that the control variable may have a
+ string value.
- Produces the result:
+ Example:
- 125
+ GTM>For x="hello":1:-1 Write !,x
+ GTM>ZWRite x
+ x=0
+ GTM>
- GT.M follows analogous syntax for routine indirection:
+ Because the argument has an increment, the FOR initializes the control
+ variable x to the numeric evaluation of "hello" (0). Then, GT.M never
+ executes the remainder of the line because the increment is positive, and
+ the value of the control variable (0) initializes to greater than the
+ limiting value (-1).
- DO ^@X(A) invokes the routine specified by X(A).
+ Example:
- DO ^@(X)(A) invokes the routine specified by X and passes the parameter A.
+ GTM>For y=-1:-3:-6,y:4:y+10,"end" Write !,y
+ -1
+ -4
+ -4
+ 0
+ 4
+ end
+ GTM>
- DO ^@X(A)(A) invokes the routine specified by X(A) and passes the
- parameter A.
+ Example:
-2 External_Calls
- External Calls
+ GTM>Set x="" For Set x=$Order(ar(x)) Quit:x="" Write !,x
- GT.M allows references to a GT.M database from programs written in other
- programming languages that run under UNIX.
+2 Goto
+ Goto
- In GT.M, calls to C language routines may be made with the following
- syntax:
+ The GOTO command transfers execution to a location specified by its
+ argument.
- DO &[packagename.]name[^name][parameter-list]
+ The format of the GOTO command is:
- or as an expression element,
+ G[OTO][:tvexpr] entryref[:tvexpr][,...]
- $&[packagename.]name[^name][parameter-list]
+3 Examples
+ Examples
- Where packagename, like the name elements is a valid M name. Because of
- the parsing conventions of M, the identifier between the ampersand (&) and
- the optional parameter-list has precisely constrained punctuation - a
- later section describes how to transform this into a more richly
- punctuated name should that be appropriate for the called function. While
- the intent of the syntax is to permit the name^name to match an M
- labelref, there is no semantic implication to any use of the caret (^).
+ Example:
- **Note**
+ GTM>GOTO TIME+4
- For more information on external calls, see Chapter 11: "Integrate
- External".
+ This GOTO command transfers control from Direct Mode to the line that is
+ four (4) lines after the line labeled TIME (in the currently active
+ routine). Using an offset is typically a debugging technique and rarely
+ used in production code.
-2 Extrinsic_Functions
- Extrinsic Functions
+ Example:
- An extrinsic function is an M subroutine that another M routine can invoke
- to return a value.
+ GOTO A:x<0,^A:x=0,A^B
- The format for extrinsic functions is:
+ This GOTO command transfers control to label A in the current routine, if
+ x is less than zero (0), to routine ^A if x is equal to zero (0), and
+ otherwise to label A in routine ^B. Once any of the transfers occurs, the
+ rest of the arguments have no effect.
- $$[label][^routinename]([expr|.lname[,...]])
+2 Halt
+ Halt
- M stacks $TEST for extrinsic functions. This is one of the two major
- differences between the DO command with parameters and extrinsics. On
- return from an extrinsic function, M restores the value of $TEST to what
- it was before the extrinsic function, regardless of the actions executed
- by the invoked routine.
+ The HALT command stops the program execution and cause GT.M to return
+ control to the operating system environment that invoked the GT.M image.
- M requires a routine that implements an extrinsic function to terminate
- with an explicit QUIT command which has an argument. M returns the value
- of the QUIT command argument as the value of the extrinsic function. This
- is the other major difference between the DO command with parameters and
- extrinsics. It is now possible to invoke a C function in a package via the
- external call mechanism.
+ The format of the HALT command is:
+
+ H[ALT][:tvexpr]
Example:
- POWER(V,X,S,T);extrinsic to raise to a power
- ;ignores fractional powers
- SET T=1,S=0
- IF X<0 SET X=-X,S=1
- FOR X=1:1:X S T=T*V
- QUIT $S(S:1/T,1:T)
- GTM> WRITE $$^POWER(3,4)
- 81
- GTM>
+ $ gtm
+ GTM>HALT
+ $
- **Note**
+ Because we invoke this GT.M image interactively, the HALT in Direct Mode
+ leaves the process at the shell prompt.
- The POWER routine uses a formallist that is longer than the "expected"
- actuallist to protect local working variables. Such practice may be
- encouraged or discouraged by your institution's standards.
+2 Hang
+ Hang
-2 Extrinsic_Special_Variables
- Extrinsic Special Variables
+ The HANG command suspends GT.M program execution for a period of time
+ specified by the command argument.
- An extrinsic special variable is a user-written M subroutine that another
- M routine can invoke to return a value.
+ The format of the HANG command is:
- The format for extrinsic special variables is:
+ H[ANG][:tvexpr] numexpr[,...]
- $$[label][^routinename]
+3 Examples
+ Examples
- An extrinsic special variable can be thought of as an extrinsic function
- without input parameters. $$x is equivalent in operation to $$x().
- Extrinsic special variables are the only case where invocation of a
- formallabel does not require an actuallist. M stacks $TEST for extrinsic
- special variables.
+ Example:
- M requires that a routine that implements an extrinsic special variable
- terminate with an explicit QUIT command which has an argument. M returns
- the value of the QUIT command argument as the value of the extrinsic
- special variable.
+ For Quit:$Data(^CTRL(1)) Hang 30
+
+ This FOR loop repeatedly tests for the existence of ^CTRL(1), and
+ terminates when that global variable exists. Otherwise the routine HANGs
+ for 30 seconds and tests again.
Example:
- GTM>ZPRINT ^DAYOWEEK
- DAYOWEEK();extrinsic special variable to
- ;provide the day of the week
- QUIT $ZD($H,"DAY")
- GTM>WRITE $$DAYOWEEK^DAYOWEEK
- MON
+ SET t=1 For Quit:$Data(^CTRL(1)) Hang t If t<30 Set t=t+1
-2 Transaction_Processing
- Transaction Processing
+ This is similar to the previous example, except that it uses an adaptive
+ time that lengthens from 1 second to a limit of 30 seconds if the routine
+ stays in the loop.
- Transaction Processing (TP) provides a way for M programs to organize
- database updates into logical groups that occur as a single event (i.e.,
- either all the database updates in a transaction occur, or none of them
- occur). No other process may behave as if it observed any intermediate
- state.
+2 If
+ If
- Transaction processing has been designed to improve output and eliminate
- "live lock" conditions. The number of attempts to complete the transaction
- is limited to four. The fourth attempt is made inside a "critical section"
- with all other processes temporarily locked out of the database. Between
- the second and third tries, GT.M waits for a random interval between 0 and
- 500 milliseconds.
+ The IF command provides conditional execution of the remaining commands on
+ the line. When IF has an argument, it updates $TEST with the truth value
+ of its evaluated argument. GT.M executes the remainder of a line after an
+ IF statement when $TEST is 1 (TRUE). When $TEST is 0 (FALSE), GT.M does
+ not execute the rest of the line.
-3 TP_Definitions
- TP Definitions
+ The format of the IF command is:
- In M, a transaction is a sequence of commands that begins with a TSTART
- command, ends with a TCOMMIT command, and is not within the scope of
- another transaction.
+ I[F] [tvexpr[,...]]
- A successful transaction ends with a COMMIT that is triggered by the
- TCOMMIT command at the end of the transaction. A COMMIT causes all the
- database updates performed within the transaction to become available to
- other processes.
+ Example:
- An unsuccessful transaction ends with a ROLLBACK. ROLLBACK is invoked
- explicitly by the TROLLBACK command, or implicitly at a process
- termination that occurs during a transaction in progress. An error within
- a transaction does not cause an implicit ROLLBACK. A ROLLBACK removes any
- database updates performed within the transaction before they are made
- available to other processes. ROLLBACK also releases all resources LOCKed
- since the start of the transaction, and makes the naked reference
- undefined.
+ IF A,B ...
+ is equivalent to
+ IF A IF B
- A RESTART is a transfer of control to the TSTART at the beginning of the
- transaction. RESTART implicitly includes a ROLLBACK and may optionally
- restore local variables to the values they had when the initial TSTART was
- originally executed. A RESTART always restores $TEST and the naked
- reference to the values they had when the initial TSTART was executed.
- RESTART does not manage device state information. A RESTART is invoked by
- the TRESTART command or by M if it is determined that the transaction is
- in conflict with other database updates. RESTART can only successfully
- occur if the initial TSTART includes an argument that enables RESTART.
+ An IF with more than one argument behaves as if those arguments were
+ logically "ANDed." However, execution of the line ceases with the
+ evaluation of the first false argument. For IF argument expressions
+ containing the "AND" operator (&), execution still ceases with the
+ evaluation of the first false argument. Any global references within the
+ expression act in sequence to maintain the naked reference.
-3 TP_Performance
- TP Performance
+3 Examples
+ Examples
- To achieve the best GT.M performance, transactions should:
+ Example:
- * be as short as possible
- * consist, as much as possible, only of global updates
- * be SERIAL with no associated LOCKs
- * have RESTART enabled with a minimum of local variables protected by a
- restart portion of the TSTART argument.
- * Large concurrent transactions using TCOMMIT may result in repeated and
- inefficient attempts by competing processes to capture needed scarce
- resources, resulting in poor performance.
+ IF x=+x!(x="") Do BAL
+
+ In this example, the DO executes if x contains a number or a null string.
Example:
- TSTART ():SERIAL
- SET (ACCT,^M(0))=^M(0)+1
- SET ^M(ACCT)=PREC,^PN(NAM)=ACCT
- TCOMMIT
+ Write !,?50,BAL If 'BAL Write "****"
+ IF Set EMPTY(acct)=""
+
+ The IF in the first line changes the value of $TEST, determining the
+ execution of the code following the argumentless IF in the second line.
+ Such argumentless IFs may serve as a form of line continuation.
Example:
- TSTART ():SERIAL
- IF $TRESTART>3 DO QUIT
- .TROLLBACK
- .WRITE !,"Too many RESTARTs"
- .QUIT
- SET (NEXT,^ID(0))=^ID(0)+1
- SET ^ID(NEXT)=RECORD,^XID(ZIP,NEXT)=""
- TCOMMIT
+ GTM>Set X=1,Y=1,Z=2 Kill UNDEF
-1 Commands
- Commands
+ GTM>If X=1,Y=1,Z=3,UNDEF=0 Write "HI"
- This chapter describes M language commands implemented in GT.M. All
- commands starting with the letter Z are GT.M additions to the ANSI
- standard command set. The M standard specifies standard abbreviations for
- commands and rejects any non-standard abbreviation.
+ GTM>
-2 Break
- Break
+ The IF command causes GT.M to cease executing the line after it determines
+ Z is not equal to three (3). Therefore, GT.M never evaluates the reference
+ to the undefined variable and never generates an error.
- The BREAK command pauses execution of the code and initiates Direct Mode.
+ Example:
- The format of the BREAK command is:
+ GTM>Set X=1 Kill UNDEF
+ GTM>If X=1!(UNDEF=3) Write "HI"
+ HI
+ GTM>
- B[REAK][:tvexpr] [expr[:tvexpr][,...]]
+2 Job
+ Job
- Issuing a BREAK command inside an M transaction destroys the Isolation of
- that transaction. Because of the way that GT.M implements transaction
- processing, a BREAK within a transaction may cause the transaction to
- suffer an indefinite number of restarts ("live lock").
+ The JOB command initiates another GT.M process that executes the named
+ routine.
- ZCONTINUE resumes execution of the interrupted program.
+ $ZJOB is set to the pid of the process created by the JOB command.
- The VIEW "BREAKMSG" mask selectively enables or disables these messages.
- By default, a process executing a GT.M image displays all BREAK messages.
+ The format of the JOB command is:
-3 Examples
- Examples
+ J[OB][:tvexpr] entryref[(expr[,...])]
+ [:[(keyword[=value][:...])][:numexpr]][,...]
- Example:
+3 The_JOB_Environment
+ The JOB Environment
- LOOP0 F S act=$O(^act(act)) Q:act="" B:debug D LOOP1
+ When the JOB is forked, UNIX creates the environment for the new process
+ by copying the environment of the process issuing the JOB command and
+ making a few minor modifications. By default, the standard input is
+ assigned to the null device, the standard output is assigned to
+ routinename.mjo, and the standard error is assigned to routinename.mje.
- This FOR loop contains a BREAK with a command postconditional.
+3 JOB_Processparameters
+ JOB Processparameters
- Example:
+ The following sections describe the processparameters available for the
+ JOB command in GT.M.
- GTM>ZPRINT ^br
- br;
- kill
- for i=1:1:3 do break;
- quit
- break;
- write "Iteration ",i,?15,"x=",$get(x,"<UNDEF>"),!
- break:$data(x) "write ""OK"",!":x,"write ""Wrong again"",!":'x
- set x=$increment(x,$data(x))
- quit
- GTM>DO ^br
- Iteration 1 x=<UNDEF>
- Iteration 2 x=0
- %GTM-I-BREAK, Break instruction encountered
- At M source location break+2^br
- GTM>ZCONTINUE
- Wrong again
- %GTM-I-BREAK, Break instruction encountered
- At M source location break+2^br
+4 CMD[LINE]="strlit"
+ CMD[LINE]="strlit"
- GTM>ZCONTINUE
- Iteration 3 x=1
- OK
- %GTM-I-BREAK, Break instruction encountered
- At M source location break+2^br
+ The string literal specifies the $ZCMDLINE of the JOB'd process.
- GTM>ZCONTINUE
- %GTM-I-BREAK, Break instruction encountered
- At M source location break+2^br
-
- GTM>ZCONTINUE
-
- GTM>
-
- This uses a BREAK with both command and argument postconditionals. The
- actions display debugging messages.
+4 DEF[AULT]=strlit
+ DEF[AULT]=strlit
-2 Close
- Close
+ The string literal specifies the default directory.
- The CLOSE command breaks the connection between a process and a device.
+ The maximum directory length is 255 characters.
- The format of the CLOSE command is:
+ If the JOB command does not specify a DEFAULT directory, GT.M uses the
+ current default directory of the parent process.
- C[LOSE][:tvexpr] expr[:(keyword[=expr][:...])][,...]
+4 ERR[OR]=strlit
+ ERR[OR]=strlit
-2 Do
- Do
+ strlit specifies the stderr of the JOBbed process. strlit can either be a
+ file or a DETACHed socket (that is, a socket from the socket pool). To
+ pass a DETACHed socket as the stderr of the JOBbed process, specify strlit
+ in the form of "SOCKET:<handle>" where <handle> is the socket handle. On
+ successful completion of the JOBbed process, the passed socket is closed
+ and is no longer available to the parent process.
- The DO command makes an entry in the GT.M invocation stack and transfers
- execution to the location specified by the entryref.
+ The maximum string length is 255 characters.
- The format of the DO command is:
+ By default, JOB constructs the error file from the routinename using a
+ file extension of .mje: the default directory of the process created by
+ the JOB command.
- D[O][:tvexpr] [entryref[(expr|.lvn[,...])][:tvexpr][,...]]
+4 GBL[DIR]=strlit
+ GBL[DIR]=strlit
-3 Examples
- Examples
+ The string literal specifies a value for the environment variable
+ gtmgbldir.
- Example:
+ The maximum string length is 255 characters.
- GTM>DO ^%RD
+ By default, the job uses the same specification for gtmgbldir as that
+ defined in $ZGBLDIR for the process using the JOB command.
- This example invokes the routine directory utility program (%RD) from
- Direct Mode. The caret symbol (^) specifies that the DO command invokes
- %RD as an external routine.
+4 IN[PUT]=strlit
+ IN[PUT]=strlit
- Example:
+ strlit specifies the stdin of the JOBbed process. strlit can either be a
+ file or a DETACHed socket (that is, a socket from the socket pool). To
+ pass a DETACHed socket as the stdin of the JOBbed process, specify strlit
+ in the form of "SOCKET:<handle>" where <handle> is the socket handle. On
+ successful completion of the JOBbed process, the passed socket is closed
+ and is no longer available to the parent process.
- GTM>DO A(3)
+ **Note**
- This example invokes the subroutine at label A and passes the value 3 as a
- parameter. The DO argument does not have a caret symbol (^), therefore, it
- identifies A as a label in the current routine.
+ Specify a DETACHed socket in both INPUT and OUTPUT parameters to pass it
+ as the $PRINCIPAL of the JOBbed process.
- Example:
+ The maximum string length is 255 characters.
- ReportA ; Label for ReportA
- SET di="" OPEN outfile USE outfile
- FOR SET di=$ORDER(^div(di)) QUIT:di="" DO PREP DO DO POST
- .SET de="",(nr,gr)=0
- .WRITE "Division ",di,! F S de=$ORDER(^de(di,de)) QUIT:de="" DO
- ..WRITE "Department ",de," Gross Rev: ",^grev(di,de),!
- ..WRITE "Department ",de," Net Rev: ",^nrev(di,de),!
- ..SET gr=gr+^grev(di,de),nr=nr+^nrev(di,de)
- .W "Division Gross Rev: ",gr,!,"Division Net Rev: ",nr,!
- DO PRINT^OUTPUT(outfile)
- QUIT
+ GT.M does not supply a default file extension.
- Example:
+ By default, the job takes its input from the null device.
- GTM>zprint ^SQR
- SQR(z);
- set revert=0
- if $view("undef") set revert=1 view "noundef"
- if z="" write "Missing parameter.",! view:revert "undef" quit
- else write z*z,! view:revert "undef" quit
+4 OUT[PUT]=strlit
+ OUT[PUT]=strlit
- GTM>do ^SQR(10)
- 100
+ strlit specifies the stdout of the JOBbed process. strlit can either be a
+ file or a DETACHed socket (that is, a socket from the socket pool). To
+ pass a DETACHed socket as the stdout of the job, specify strlit in the
+ form of "SOCKET:<handle>" where <handle> is the socket handle. On
+ successful completion of the JOBbed process, the passed socket is closed
+ and is no longer available to the parent process.
- GTM>do ^SQR
- Missing parameter.
+ **Note**
- This examples demonstrates label invocations using DO with and without
- parentheses.
+ Specify a DETACHed socket in both INPUT and OUTPUT parameters to pass it
+ as the $PRINCIPAL of the JOBbed process.
-2 Else
- Else
+ The maximum string length is 255 characters.
- ELSE executes the remainder of the line after the ELSE if $TEST is FALSE
- (0). GT.M does not execute the rest of the line if $TEST is TRUE (1).
+ By default, JOB constructs the output file pathname from the routinename
+ using a file extension of .mjo and the current default directory of the
+ process created by the JOB command.
- The format of the ELSE command is:
+4 STA[RTUP]="/path/to/shell/script"
+ STA[RTUP]="/path/to/shell/script"
- E[LSE]
+ Specifies the location of the shell script that executes before running
+ the named routine.
- ELSE is analogous to IF '$TEST, except the latter statement switches $TEST
- to its complement and ELSE never alters $TEST.
+ The JOBbed process spawns a shell session to execute the shell script. If
+ the shell script fails, the JOB'd process terminates without running the
+ named routine. Because STARTUP executes in a separate shell, it has no
+ impact on the environment of the JOB'd process, which is inherited from
+ the parent. STARTUP is useful for actions such as creating directories.
+ Use PIPE devices instead of the JOB command to control the environment of
+ a spawned process.
3 Examples
Examples
Example:
- If x=+x Set x=x+y
- Else Write !,x
+ GTM>JOB ^TEST("V54001","")
- The IF command evaluates the conditional expression x=+x and sets $TEST.
- If $TEST=1 (TRUE), GT.M executes the commands following the IF. The ELSE
- on the following line specifies an alternative action to take if the
- expression is false.
+ This creates a job that starts doing the routine ^TEST (with 2 parameters)
+ in the current working directory.
Example:
- If x=+x Do ^GOFISH
- Else Set x=x_"^"_y
+ JOB PRINTLABELS(TYPE,PRNTR,WAITIM)
- The DO with an argument after the IF raises the possibility that the
- routine ^GOFISH changes the value of $TEST, thus making it possible to
- execute both the commands following the IF and the commands following the
- ELSE.
+ This passes three values (TYPE, PRNTR, and WAITIM) to the new job, which
+ starts at the label PRINTLABELS of the current routine.
Example:
- Open dev::0 Else Write !,"Device unavailable" QUIT
-
- This ELSE depends on the result of the timeout on the OPEN command. If the
- OPEN succeeds, it sets $TEST to one (1) and GT.M skips the rest of the
- line after the ELSE. If the OPEN fails, it sets $TEST to zero (0), and
- GT.M executes the remainder of the line after the ELSE.
+ Refer to the sockexamplemulti3.m program in "Socket Device
+ Examples" for more examples on the JOB command.
-2 For
- For
+2 Kill
+ Kill
- The FOR command provides a looping mechanism in GT.M. FOR does not
- generate an additional level in the M standard stack model.
+ The KILL command deletes local or global variables and their descendant
+ nodes.
- The format of the FOR command is:
+ The format of the KILL command is:
- F[OR][lvn=expr[:numexpr1[:numexpr2]][,...]]]
+ K[ILL][:tvexpr] [glvn | (glvn[,...]) | *lname | *lvn ]
3 Examples
Examples
Example:
- GTM>Kill i For i=1:1:5 Write !,i
- 1
- 2
- 3
- 4
- 5
- GTM>Write i
- 5
+ GTM>Kill Set a=0,a(1)=1,a(1,1)="under" KILL a(1) ZWR
+ a=0
GTM>
- This FOR loop has a control variable, i, which has the value one (1) on
- the first iteration, then the value two (2), and so on, until in the last
- iteration i has the value five (5). The FOR terminates because
- incrementing i would cause it to exceed the limit. Notice that i is not
- incremented beyond the limit.
+ This uses an argumentless KILL to get a "fresh start" by deleting all
+ existing local variables. After SETting a, a(1), and a(1,1), the KILL
+ deletes a(1) and its descendants. The ZWRITE shows only a remaining.
Example:
- GTM>FOR x="hello",2,"goodbye" WRITE !,x
- hello
- 2
- goodbye
- GTM>
+ GTM>Kill (a,b),^AB(a,b)
- This FOR loop uses the control variable x and a series of arguments that
- have no increments or limits. Notice that the control variable may have a
- string value.
+ The first argument (an exclusive KILL) specifies to KILL all local
+ variables except a and b. The second argument deletes ^AB(a,b) and any
+ descendants of that global variable node.
Example:
- GTM>For x="hello":1:-1 Write !,x
- GTM>ZWRite x
- x=0
- GTM>
-
- Because the argument has an increment, the FOR initializes the control
- variable x to the numeric evaluation of "hello" (0). Then, GT.M never
- executes the remainder of the line because the increment is positive, and
- the value of the control variable (0) initializes to greater than the
- limiting value (-1).
+ kill *
- Example:
+ write !,"gtm_stdxkill=",+$ztrnlnm("gtm_stdxkill"),!
- GTM>For y=-1:-3:-6,y:4:y+10,"end" Write !,y
- -1
- -4
- -4
- 0
- 4
- end
- GTM>
+ set (A,B,C,E)="input"
+ do X(.A,.B)
+ zwrite
- Example:
+ write !,"____________",!
+ set (A,B,C,E)="input"
+ do Y(.A,.B)
+ zwrite
+ write !,"____________",!
+ set (A,B,C,E)="base"
+ set *C=A,*D=B
+ kill (C,D)
+ zwrite
+ quit
+ X(C,D) set (C,D)="output"
+ kill (C,D)
+ quit
+ Y(C,D) set (C,D)="output"
+ kill (A,C,D)
+ quit
- GTM>Set x="" For Set x=$Order(ar(x)) Quit:x="" Write !,x
+ Produces the following output:
-2 Goto
- Goto
+ gtm_stdxkill=0
+ A="output"
+ B="output"
+ C="input"
- The GOTO command transfers execution to a location specified by its
- argument.
+ ____________
+ A="output"
+ B="output"
+ C="input"
- The format of the GOTO command is:
+ ____________
+ A="base" ;*
+ B="base" ;*
+ *C=A
+ *D=B
- G[OTO][:tvexpr] entryref[:tvexpr][,...]
+2 Lock
+ Lock
-3 Examples
- Examples
+ The LOCK command reserves and releases resource names, and provides a
+ semaphore capability for GT.M processes. This capability can be used for
+ interprocess synchronization and signaling.
- Example:
+ Assigning a LOCK does not specify any explicit control over variables and
+ does not directly effect either read or write access to global (or local)
+ data. However, an application that adheres to clearly defined conventions
+ of LOCKing before any access can indirectly achieve such an effect.
- GTM>GOTO TIME+4
+ FIS recommends implementing database Consistency using transaction
+ processing rather than LOCKs. If you wish to avoid GT.M's use of
+ optimistic concurrency for TP, place the LOCK just before the original
+ TSTART and release it after the final TCOMMIT.
- This GOTO command transfers control from Direct Mode to the line that is
- four (4) lines after the line labeled TIME (in the currently active
- routine). Using an offset is typically a debugging technique and rarely
- used in production code.
+ The format of the LOCK command is:
- Example:
+ L[OCK][:tvexpr] [[-|+]nref|(nref[,...])[:numexpr] [,...]]
- GOTO A:x<0,^A:x=0,A^B
-
- This GOTO command transfers control to label A in the current routine, if
- x is less than zero (0), to routine ^A if x is equal to zero (0), and
- otherwise to label A in routine ^B. Once any of the transfers occurs, the
- rest of the arguments have no effect.
+2 Merge
+ Merge
-2 Halt
- Halt
+ The MERGE command copies a variable and all its descendants into another
+ variable. MERGE does not delete the destination variable, nor any of its
+ descendants.
- The HALT command stops the program execution and cause GT.M to return
- control to the operating system environment that invoked the GT.M image.
+ The format of MERGE command is:
- The format of the HALT command is:
+ M[ERGE][:tvexpr] glvn1=glvn2[,...]
- H[ALT][:tvexpr]
+3 Examples
+ Examples
Example:
- $ gtm
- GTM>HALT
- $
+ GTM>Set ^gbl1="one"
- Because we invoke this GT.M image interactively, the HALT in Direct Mode
- leaves the process at the shell prompt.
+ GTM>Set ^gbl1(1,1)="oneone"
-2 Hang
- Hang
+ GTM>Set ^gbl1(1,1,3)="oneonethree"
- The HANG command suspends GT.M program execution for a period of time
- specified by the command argument.
+ GTM>Set ^gbl1(1,2,4)="onetwofour"
- The format of the HANG command is:
+ GTM>Set ^gbl2(2)="gbl2_2"
- H[ANG][:tvexpr] numexpr[,...]
+ GTM>Set ^gbl2(2,1,3)="gbl2_2_1_3"
-3 Examples
- Examples
+ GTM>Set ^gbl2(2,1,4,5)="gbl2_2_1_4_5"
- Example:
+ GTM>Merge ^gbl1(1)=^gbl2(2)
- For Quit:$Data(^CTRL(1)) Hang 30
+ GTM>WRITE $Reference
+ ^gbl1(1)
+ GTM>ZWRite ^gbl1
+ ^gbl1="one"
+ ^gbl1(1)="gbl2_2"
+ ^gbl1(1,1)="oneone"
+ ^gbl1(1,1,3)="gbl2_2_1_3"
+ ^gbl1(1,1,4,5)="gbl2_2_1_4_5"
+ ^gbl1(1,2,4)="onetwofour"
+ GTM>ZWRITE ^gbl2
+ ^gbl2(2)="gbl2_2"
+ ^gbl2(2,1,3)="gbl2_2_1_3"
+ ^gbl2(2,1,4,5)="gbl2_2_1_4_5"
+ GTM>
- This FOR loop repeatedly tests for the existence of ^CTRL(1), and
- terminates when that global variable exists. Otherwise the routine HANGs
- for 30 seconds and tests again.
+ This example illustrates how MERGE copies a sub-tree of one global into
+ another. The nodes in the sub-tree of ^gbl(2), for which $DATA() value is
+ 1 or 11, are copied to sub-tree of ^gbl1(1) as follows:
+
+ ^gbl1(1) is updated from the value of ^gbl2(2)
+ ^gbl1(1,1,3) is updated from the value of ^gbl2(2,1,3)
+ ^gbl1(1,1,4,5) is updated from the value of ^gbl2(2,1,4,5)
+
+ Since ^gbl1(2,1) and ^gbl2(2,2,4) do not have values ($DATA()=0), the
+ corresponding nodes ^gbl1(1,1) and ^gbl(1,2,4) respectively are left
+ unchanged. The naked indicator takes the value ^gbl(1) as if SET replaced
+ MERGE. Notice that the MERGE command does not change ^gbl2(2) or its
+ descendants. Ancestor nodes of ^gbl(1) are also left unchanged.
Example:
- SET t=1 For Quit:$Data(^CTRL(1)) Hang t If t<30 Set t=t+1
+ GTM>Kill
- This is similar to the previous example, except that it uses an adaptive
- time that lengthens from 1 second to a limit of 30 seconds if the routine
- stays in the loop.
+ GTM>Set ^gbl(1,2)="1,2"
-2 If
- If
+ GTM>Merge lcl(3,4)=^gbl(1)
- The IF command provides conditional execution of the remaining commands on
- the line. When IF has an argument, it updates $TEST with the truth value
- of its evaluated argument. GT.M executes the remainder of a line after an
- IF statement when $TEST is 1 (TRUE). When $TEST is 0 (FALSE), GT.M does
- not execute the rest of the line.
+ GTM>Set ^("naked")=2
- The format of the IF command is:
+ GTM>ZWRite ^gbl
+ ^gbl(1,2)="1,2"
+ ^gbl("naked")=2
+ GTM>ZWRite lcl
+ lcl(3,4,2)="1,2"
+ GTM>
- I[F] [tvexpr[,...]]
+ This example illustrates how MERGE creates a sub-tree of a variable when
+ the variable does not exist. Also, notice how the naked indicator is set
+ when the source of the MERGE is a global and the destination a local.
- Example:
+2 New
+ New
- IF A,B ...
- is equivalent to
- IF A IF B
+ The NEW command "stacks" copies of local variables and reinitializes those
+ variables. An explicit or implicit QUIT from a DO, XECUTE or extrinsic
+ function "unstacks" the NEWed variables, that is, restores the variable to
+ the stacked value. A NEW lasts only while the current scope of execution
+ is active.
- An IF with more than one argument behaves as if those arguments were
- logically "ANDed." However, execution of the line ceases with the
- evaluation of the first false argument. For IF argument expressions
- containing the "AND" operator (&), execution still ceases with the
- evaluation of the first false argument. Any global references within the
- expression act in sequence to maintain the naked reference.
+ The format of the NEW command is:
+
+ N[EW][:tvexpr] [[(]lvn[,...][)][,...]]
3 Examples
Examples
Example:
- IF x=+x!(x="") Do BAL
-
- In this example, the DO executes if x contains a number or a null string.
-
- Example:
+ NEW1;
+ Set A(1)=1,B=4,C=5
+ Write !,"VARIABLES BEFORE NEW:",!
+ ZWRite
+ Do LABEL
+ Write !,"VARIABLES AFTER RETURN:",!
+ ZWRite
+ Quit
+ LABEL
+ New A Set C=7
+ Write !,"VARIABLES AFTER NEW:",!
+ ZWRite
+ Quit
- Write !,?50,BAL If 'BAL Write "****"
- IF Set EMPTY(acct)=""
+ Produces the results:
- The IF in the first line changes the value of $TEST, determining the
- execution of the code following the argumentless IF in the second line.
- Such argumentless IFs may serve as a form of line continuation.
+ VARIABLES BEFORE NEW:
+ A(1)=1
+ B=4
+ C=5
+ VARIABLES AFTER NEW:
+ B=4
+ C=7
+ VARIABLES AFTER RETURN:
+ A(1)=1
+ B=4
+ C=7
Example:
- GTM>Set X=1,Y=1,Z=2 Kill UNDEF
-
- GTM>If X=1,Y=1,Z=3,UNDEF=0 Write "HI"
+ NEW2;
+ Set (A,B,C,D)="TEST"
+ Do LABEL
+ Write !,"VARIABLES AFTER RETURN:",!
+ ZWRite
+ Quit
+ LABEL
+ New (B,C) SET (A,B,Z)="NEW"
+ Write !,"VARIABLES AFTER EXCLUSIVE NEW:",!
+ ZWRite
+ Quit
- GTM>
+ Produces the results:
- The IF command causes GT.M to cease executing the line after it determines
- Z is not equal to three (3). Therefore, GT.M never evaluates the reference
- to the undefined variable and never generates an error.
+ VARIABLES AFTER EXCLUSIVE NEW:
+ A="NEW"
+ B="NEW"
+ C="TEST"
+ Z="NEW"
+ VARIABLES AFTER RETURN:
+ A="TEST"
+ B="NEW"
+ C="TEST"
+ D="TEST"
Example:
- GTM>Set X=1 Kill UNDEF
- GTM>If X=1!(UNDEF=3) Write "HI"
- HI
- GTM>
-
-2 Job
- Job
-
- The JOB command initiates another GT.M process that executes the named
- routine.
-
- $ZJOB is set to the pid of the process created by the JOB command.
-
- The format of the JOB command is:
-
- J[OB][:tvexpr] entryref[(expr[,...])]
- [:[(keyword[=value][:...])][:numexpr]][,...]
-
-3 The_JOB_Environment
- The JOB Environment
-
- When the JOB is forked, UNIX creates the environment for the new process
- by copying the environment of the process issuing the JOB command and
- making a few minor modifications. By default, the standard input is
- assigned to the null device, the standard output is assigned to
- routinename.mjo, and the standard error is assigned to routinename.mje.
+ /usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^stackalias
+ stackalias ; Demonstrate New with alias
+ ZPrint ; Print this program
+ Set A=1,*B=A,*C(2)=A ; Create some aliases
+ Write "------------",!
+ Write "ZWRite in the caller before subprogram",!
+ ZWRite
+ Do S1 ; Call a subprogram
+ Write "------------",!
+ Write "ZWRite in the caller after subprogram - A association is restored",!
+ ZWRite
+ Quit
+ ;
+ S1 ; Subprogram
+ New A
+ Set A="I am not an alias",B="I am an alias"
+ Write "------------",!
+ Write "ZWRite in the subprogram with new A and modified B",!
+ ZWRite
+ Quit
+ ------------
+ ZWRite in the caller before subprogram
+ A=1 ;*
+ *B=A
+ C=3
+ *C(2)=A
+ D=4
+ ------------
+ ZWRite in the subprogram with new A and modified B
+ A="I am not an alias"
+ B="I am an alias" ;*
+ C=3
+ *C(2)=B
+ D=4
+ ------------
+ ZWRite in the caller after subprogram - A association is restored
+ A="I am an alias" ;*
+ *B=A
+ C=3
+ *C(2)=A
+ D=4
-3 JOB_Processparameters
- JOB Processparameters
+ The following is essentially the same as the prior example but using an
+ exclusive NEW:
- The following sections describe the processparameters available for the
- JOB command in GT.M.
-
-4 CMD[LINE]="strlit"
- CMD[LINE]="strlit"
-
- The string literal specifies the $ZCMDLINE of the JOB'd process.
-
-4 DEF[AULT]=strlit
- DEF[AULT]=strlit
-
- The string literal specifies the default directory.
-
- The maximum directory length is 255 characters.
-
- If the JOB command does not specify a DEFAULT directory, GT.M uses the
- current default directory of the parent process.
+ $ /usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^stackalias1
+ stackalias1 ; Demonstrate New with alias
+ ZPrint ; Print this program
+ Set A=1,*B=A,*C(2)=A ; Create some aliases
+ Write "------------",!
+ Write "ZWRite in the caller before subprogram",!
+ ZWRite
+ Do S1 ; Call a subprogram
+ Write "------------",!
+ Write "ZWRite in the caller after subprogram - A association is restored",!
+ ZWRite
+ Quit
+ ;
+ S1 ; Subprogram
+ New (B)
+ Set A="I am not an alias",B="I am an alias"
+ Write "------------",!
+ Write "ZWRite in the subprogram - Notice B is flagged as an alias",!
+ ZWRite
+ Quit
+ ------------
+ ZWRite in the caller before subprogram
+ A=1 ;*
+ *B=A
+ C=3
+ *C(2)=A
+ D=4
+ ------------
+ ZWRite in the subprogram - Notice B is flagged as an alias
+ A="I am not an alias"
+ B="I am an alias" ;*
+ ------------
+ ZWRite in the caller after subprogram - A association is restored
+ A="I am an alias" ;*
+ *B=A
+ C=3
+ *C(2)=A
+ D=4
-4 ERR[OR]=strlit
- ERR[OR]=strlit
+ An exclusive New can create a scope in which only one association between
+ a name or an lvn and an array may be visible. In this case, ZWRITE
+ nevertheless shows the existence of an alias, even when that array is
+ accessible from only one name or lvn.
- The string literal specifies a value for stderr.
+2 Open
+ Open
- The maximum string length is 255 characters.
+ The OPEN command creates a connection between a GT.M process and a device.
- By default, JOB constructs the error file from the routinename using a
- file extension of .mje: the default directory of the process created by
- the JOB command.
+ The format of the OPEN command is:
-4 GBL[DIR]=strlit
- GBL[DIR]=strlit
+ O[PEN][:tvexpr] expr[:[(keyword[=expr][:...])] [:numexpr]][,...]
- The string literal specifies a value for the environment variable
- gtmgbldir.
+2 Quit
+ Quit
- The maximum string length is 255 characters.
+ Except when a QUIT appears on a line after a FOR, the QUIT command
+ terminates execution of the current GT.M invocation stack level initiated
+ by a DO, XECUTE, extrinsic function or special variable, and return
+ control to the next "lower" level. In this case, QUIT restores any values
+ stacked at the current level by NEWs or by parameter passing. A QUIT
+ command terminates any closest FOR command on the same line. Note that M
+ overloads the QUIT command to terminate DO, FOR, XECUTE and extrinsics
+ ($$) of which FOR is the most different.
- By default, the job uses the same specification for gtmgbldir as that
- defined in $ZGBLDIR for the process using the JOB command.
+ The format of the QUIT command is:
-4 IN[PUT]=strlit
- IN[PUT]=strlit
+ Q[UIT][:tvexpr] [expr | *lname | *lvn]
- The string literal specifies a value for stdin.
+3 Examples
+ Examples
- The maximum string length is 255 characters.
+ Example:
- GT.M does not supply a default file extension.
+ Do A
+ Quit
+ A Write !,"This is label A"
- By default, the job takes its input from the null device.
+ The explicit QUIT at the line preceding the label A prevents line A from
+ executing twice. The sub-routine at line A terminates with the implicit
+ QUIT at the end of the routine.
-4 OUT[PUT]=strlit
- OUT[PUT]=strlit
+ Example:
- The string literal specifies a value for stdout.
+ Write $$ESV
+ Quit
+ ESV()
+ QUIT "value of this Extrinsic Special Variable"
- The maximum string length is 255 characters.
+ Because the label ESV has an argument list (which is empty), GT.M can only
+ legally reach that label with an extrinsic invocation. The QUIT on the
+ second line prevents execution from erroneously "falling through" to the
+ line labeled ESV. Because ESV identifies a subroutine that implements an
+ extrinsic special variable, the QUIT on the line after ESV has an argument
+ to provide the value of the extrinsic.
- By default, JOB constructs the output file pathname from the routinename
- using a file extension of .mjo and the current default directory of the
- process created by the JOB command.
+ Example:
-4 STA[RTUP]="/path/to/shell/script"
- STA[RTUP]="/path/to/shell/script"
+ Set x="" For Set x=$Order(^BAL(x)) Quit:x]]"AR5999"!'$Length(x) DO STF
- Specifies the location of the shell script that executes before running
- the named routine.
+ The postconditional QUIT terminates the FOR loop. Note the two spaces
+ after the QUIT because it has no argument.
- The JOBbed process spawns a shell session to execute the shell script. If
- the shell script fails, the JOB'd process terminates without running the
- named routine. Because STARTUP executes in a separate shell, it has no
- impact on the environment of the JOB'd process, which is inherited from
- the parent. STARTUP is useful for things like creating directories, for
- example. Use PIPE devices instead of the JOB command to control the
- environment of a spawned process.
+2 Read
+ Read
-3 Examples
- Examples
+ The READ command transfers the input from the current device to a global
+ or local variable specified as a READ argument. For convenience, READ also
+ accepts arguments that perform limited output to the current device.
- Example:
+ The format of the READ command is:
- GTM>JOB ^TEST("V54001","")
+ R[EAD][:tvexpr] (glvn|*glvn|glvn#intexpr)[:numexpr]|strlit|fcc[,...]
- This creates a job that starts doing the routine ^TEST (with 2 parameters)
- in the current working directory.
+2 Set
+ Set
- Example:
+ SET assigns values to variables or to a selected portion of a variable.
- JOB PRINTLABELS(TYPE,PRNTR,WAITIM)
+ The format of the SET command is:
- This passes three values (TYPE, PRNTR, and WAITIM) to the new job, which
- starts at the label PRINTLABELS of the current routine.
+ S[ET][:tvexpr] setleft=expr | (setleft[,...])=expr | *lvn=lname | aliascontainer[,...]
-2 Kill
- Kill
+ where
- The KILL command deletes local or global variables and their descendant
- nodes.
+ setleft == glvn | $EXTRACT(glvn,[,intexpr1[,intexpr2]]) | $PIECE(glvn,expr1[,intexpr1[,intexpr2]]) | isv
- The format of the KILL command is:
+ and
- K[ILL][:tvexpr] [glvn|[(]lvn[,...][)][,...]]
+ aliascontainer == lvn | exfunc | exvar
3 Examples
Examples
Example:
- GTM>Kill Set a=0,a(1)=1,a(1,1)="under" KILL a(1) ZWR
- a=0
+ GTM>Kill Set a="x",(b,c)=1, at a="hello" ZWRite
+ a=x
+ b=1
+ c=1
+ x="hello"
GTM>
- This uses an argumentless KILL to get a "fresh start" by deleting all
- existing local variables. After SETting a, a(1), and a(1,1), the KILL
- deletes a(1) and its descendants. The ZWRITE shows only a remaining.
+ The KILL command deletes any previously defined local variables. The SET
+ command has three arguments. The first shows a simple direct assignment.
+ The second shows the form that assigns the same value to multiple
+ variables. The third shows atomic indirection on the left of the equal
+ sign. The ZWRITE command displays the results of the assignments.
Example:
- GTM>Kill (a,b),^AB(a,b)
+ GTM>Set ^(3,4)=^X(1,2)
- The first argument (an exclusive KILL) specifies to KILL all local
- variables except a and b. The second argument deletes ^AB(a,b) and any
- descendants of that global variable node.
+ As GT.M evaluates the right-hand side of the equal sign before the
+ left-hand side within a SET argument, the right-hand expression determines
+ the naked reference indicator prior to evaluation of the left-hand side.
+ Therefore, this example assigns ^X(1,3,4) the value of ^X(1,2).
Example:
- kill *
+ GTM>Kill x Set $Piece(x,"^",2)="piece 3" ZWRite x
+ x="^^piece 3"
+ GTM>
- write !,"gtm_stdxkill=",+$ztrnlnm("gtm_stdxkill"),!
+ This SET demonstrates a "set piece" and shows how SET generates missing
+ delimiters when required.
- set (A,B,C,E)="input"
- do X(.A,.B)
- zwrite
+ Example:
- write !,"____________",!
- set (A,B,C,E)="input"
- do Y(.A,.B)
- zwrite
- write !,"____________",!
- set (A,B,C,E)="base"
- set *C=A,*D=B
- kill (C,D)
- zwrite
- quit
- X(C,D) set (C,D)="output"
- kill (C,D)
- quit
- Y(C,D) set (C,D)="output"
- kill (A,C,D)
- quit
+ GTM>Set x="I love hotdogs"
- Produces the following output:
+ GTM>Set $Extract(x,3,6)="want"
- gtm_stdxkill=0
- A="output"
- B="output"
- C="input"
+ GTM>Write x
+ I want hotdogs
+ GTM>Set $Extract(x,7)=" many "
- ____________
- A="output"
- B="output"
- C="input"
+ GTM>Write x
+ I want many hotdogs
+ GTM>
- ____________
- A="base" ;*
- B="base" ;*
- *C=A
- *D=B
+ The SET $EXTRACT command replaces and extracts the specified characters
+ with the value of the expression on the right hand side of the equal-sign
+ (=).
-2 Kill_*
- Kill *
+ Example:
- KILL * removes the association between its arguments, and any associated
- arrays. The arguments are left undefined, just as with a standard KILL. If
- the array has no remaining associations after the KILL *, GT.M can reuse
- the memory it occupied. If there are no array(s) or association(s) the
- KILL * happily and silently does nothing.
+ GTM>kill A,B
- The format of the KILL * command is:
+ GTM>set A=1,A(1)=1,A(2)=2
- K[ILL][:tvexpr] *{lvn | name}[,...]
+ GTM>set *B=A ; A & B are aliases.
-3 Examples
- Examples
+ GTM>zwrite B
+ B=1 ;*
+ B(1)=1
+ B(2)=2
- Example
+ GTM>
- GTM>Set A=1,*B=A ; Create an array and an association
+ This SET * command creates an alias associated between A and B. It
+ associates the entire tree of nodes of A including its root and all
+ descendants with B.
- GTM>ZWRite ; Show that the array and association exist
- A=1 ;*
- *B=A
- GTM>Kill *A ; Remove the association for A - it now has no association and no array
+ Example:
- GTM>ZWRite ; B is a traditional local variable
- B=1
+ GTM>kill A,B,C
- Example:
+ GTM>set A=1,*C(2)=A ; C(2) is a container
- GTM>Set A=2 ; add a value for A
+ GTM>zwrite
+ A=1 ;*
+ *C(2)=A
- GTM>ZWRite ; A and B have different values and both are traditional local variables
- A=2
- B=1
- GTM>
+ GTM>set *B=C(2) ; B is now an alias
- KILL on the other hand, removes data in the array (and possibly the array
- itself) without affecting any alias association.
+ GTM>write B,":",$length(C(2)),":" ; An alias variable provides access but a container doesn't
+ 1:0:
+ GTM>
- GTM>Set A=2,*B=A ; Create an array and an association
+ This SET * command creates an alias by dereferencing an alias container.
- GTM>ZWRite ; Both array and association exist
- A=2 ;*
- *B=A
- GTM>Kill A ; Kill the array
+2 TCommit
+ TCommit
- GTM>ZWRite ; There's no data to show - only the association
- *B=A
+ The TCOMMIT command marks the end of a transaction or sub-transaction and
+ decrements $TLEVEL. If TCOMMIT marks the end of a transaction (decrements
+ $TLEVEL to zero), it invokes a COMMIT, which makes the database updates
+ performed by the transaction generally available. A TCOMMIT issued when no
+ transaction is in progress ($TLEVEL=0) produces an error.
- GTM>Set B=3 ; Create a new value
+ The format of the TCOMMIT command is:
- GTM>ZWRite ; The association was unaffected by the Kill
- A=3 ;*
- *B=A
- GTM>
+ TC[OMMIT][:tvexpr]
- Example:
+ For an example of the use of the TCOMMIT command, refer to the chapter on
+ General Language Features of M in GT.M Programmer's Guide.
- $ /usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^killalias
- killalias ; Demonstrate Kill * of pass by reference
- ZPrint ; Print this program
- Set A=1,C=3
- Write "------------",!
- Write "Initial Values:",!
- ZWRite
- Do K1(.A,.C) ; Pass A & C by reference
- Write "------------",!
- Write "Value of A is unchanged because of Kill *B, but C has changed: ",!
- ZWRite
- Quit
- ;
- K1(B,D) ; A & C are bound to B & D respectively
- Write "------------",!
- Write "A & B are aliases, as are C & D:",!
- ZWRite
- Kill *B
- Set B=2,D=4
- Write "------------",!
- Write "After Kill *B, A & B are different but C & D remain associated:",!
- ZWrite
- Quit
- ------------
- Initial Values:
- A=1
- C=3
- ------------
- A & B are aliases, as are C & D:
- A=1 ;*
- *B=A
- C=3 ;*
- *D=C
- ------------
- After Kill *B, A & B are different but C & D remain associated:
- A=1
- B=2
- C=4 ;*
- *D=C
- ------------
- Value of A is unchanged because of Kill *B, but C has changed:
- A=1
- C=4
+2 TREstart
+ TREstart
- Example:
+ The TRESTART command attempts to RESTART the current transaction. A
+ RESTART transfers control back to the initial TSTART and restores much of
+ the process state to what it was when that TSTART was originally executed.
+ A TRESTART issued when no transaction is in progress ($TLEVEL=0) or when
+ the transaction does not have RESTART enabled produces an error.
- GTM>Set A=1,*B=A ; Create an array and association
- GTM>ZWRite ; Verify that it's there
- A=1 ;*
- *B=A
+ A TRESTART command causes the TP transaction to RESTART in the same way
+ that GT.M uses to implicitly restart the transaction in case of resource
+ conflicts. All restarts increment the internal transaction retry count to
+ a maximum of three (3), at which point, GT.M performs the entire TP
+ transaction within a critical section on all databases referenced in the
+ transaction.
- GTM>Kill (A) ; Kill everything except A
+ GT.M issues a TRESTMAX runtime error when application code attempts a
+ TRESTART more than once during a transaction while $TRESTART=4 (note: in
+ order to be wholesome, TRESTART usage in application code should always be
+ conditional). In the final retry, GT.M holds the critical section lock on
+ all databases involved in the transaction. Since a TRESTART cancels all
+ the work done in the current transaction and transfers control back to the
+ TSTART, limiting the number of times this can be done in the final retry
+ limits the time a process can (by virtue of holding a critical section
+ lock on the databases) prevent other processes from updating the database.
- GTM>ZWRite ; Demonstrate that A also has no array
+ GT.M limits TP restarts in the final retry due to non-availability of
+ M-locks in a similar fashion. GT.M allows a maximum of 16 such restarts
+ after which it issues a TPLOCKRESTMAX runtime error.
- GTM>Set A=2 ; Create an array
+ The format for the TRESTART command is:
- GTM>ZWRite ; The association survived the Kill
- A=2 ;*
- *B=A
- GTM>
+ TRE[START][:tvexpr]
-2 Lock
- Lock
+ For an example of the use of the TRESTART command, refer to the chapter on
+ "General Language Features of M" in the GT.M Programmer's Guide.
- The LOCK command reserves and releases resource names, and provides a
- semaphore capability for GT.M processes. This capability can be used for
- interprocess synchronization and signaling.
+2 TROllback
+ TROllback
- Assigning a LOCK does not specify any explicit control over variables and
- does not directly effect either read or write access to global (or local)
- data. However, an application that adheres to clearly defined conventions
- of LOCKing before any access can indirectly achieve such an effect.
+ The TROLLBACK command terminates a transaction by causing a ROLLBACK,
+ which removes all database updates performed within a transaction. A
+ TROLLBACK without an argument also sets $TLEVEL and $TRESTART to zero (0).
+ Issuing a TROLLBACK when no transaction is in progress ($TLEVEL=0)
+ produces an error.
- FIS recommends implementing database Consistency using transaction
- processing rather than LOCKs. If you wish to avoid GT.M's use of
- optimistic concurrency for TP, place the LOCK just before the original
- TSTART and release it after the final TCOMMIT.
+ The format of the TROLLBACK command is:
- The format of the LOCK command is:
+ TRO[LLBACK][:tvexpr] [intexpr]
- L[OCK][:tvexpr] [[-|+]nref|(nref[,...])[:numexpr] [,...]]
+ For an example of the use of the TROLLBACK command, refer to the chapter
+ on "General Language Features of M" in the GT.M Programmer's Guide.
-2 Merge
- Merge
+2 TStart
+ TStart
- The MERGE command copies a variable and all its descendants into another
- variable. MERGE does not delete the destination variable, nor any of its
- descendants.
+ The TSTART command marks the beginning of a transaction or sub-transaction
+ and increments $TLEVEL. When TSTART marks the beginning of a transaction
+ ($TLEVEL=1), its arguments determine whether the transaction may RESTART
+ and whether serializability is enforced. If a transaction may RESTART, the
+ TSTART arguments determine which local variables are restored during a
+ RESTART. Serializability is enforced by LOCK commands or, if the SERIAL
+ keyword is specified, by GT.M.
- The format of MERGE command is:
+ The format of the TSTART command is:
- M[ERGE][:tvexpr] glvn1=glvn2[,...]
+ TS[TART][:tvexpr] [([lvn...])|lvn|*|][:keyword|(keyword...)]
-3 Examples
- Examples
+ For an example of the TSTART command, refer to the chapter on "General
+ Language Features of M" in the GT.M Programmer's Guide.
- Example:
+3 S[ERIAL]
+ S[ERIAL]
- GTM>Set ^gbl1="one"
+ The SERIAL keyword indicates that GT.M must ensure the serializability of
+ the transaction. Note that GT.M always serializes transactions regardless
+ of the SERIAL keyword. On a nested TSTART, this portion of the argument is
+ irrelevant.
- GTM>Set ^gbl1(1,1)="oneone"
+3 T[RANSACTIONID]=expr
+ T[RANSACTIONID]=expr
- GTM>Set ^gbl1(1,1,3)="oneonethree"
+ The TRANSACTIONID keyword declares an arbitrary transaction
+ identification.
- GTM>Set ^gbl1(1,2,4)="onetwofour"
+ If TRANSACTIONID="BATCH" or "BA" at transaction completion, the process
+ immediately continues execution. When a process issues a [final] TCOMMIT
+ for a transaction and journaling is active, by default the process waits
+ until the entire transaction is written to the journal file(s) before
+ executing the next command. This ensures that every transaction is durable
+ before the process moves on to the next step. Transactions flagged as
+ "BATCH" have lower latency and higher throughput, but a lower guarantee of
+ durability. Normally this flag is used when operational procedures (such
+ as a backup) or application code (such as a checkpoint algorithm) provides
+ an acceptable alternative means of ensuring durability.
- GTM>Set ^gbl2(2)="gbl2_2"
+2 Use
+ Use
- GTM>Set ^gbl2(2,1,3)="gbl2_2_1_3"
+ The USE command selects the current device for READs (input) and WRITEs
+ (output).
- GTM>Set ^gbl2(2,1,4,5)="gbl2_2_1_4_5"
+ The format of the USE command is:
- GTM>Merge ^gbl1(1)=^gbl2(2)
+ U[SE][:tvexpr] expr[:(keyword[=expr][:...])][,...]
- GTM>WRITE $Reference
- ^gbl1(1)
- GTM>ZWRite ^gbl1
- ^gbl1="one"
- ^gbl1(1)="gbl2_2"
- ^gbl1(1,1)="oneone"
- ^gbl1(1,1,3)="gbl2_2_1_3"
- ^gbl1(1,1,4,5)="gbl2_2_1_4_5"
- ^gbl1(1,2,4)="onetwofour"
- GTM>ZWRITE ^gbl2
- ^gbl2(2)="gbl2_2"
- ^gbl2(2,1,3)="gbl2_2_1_3"
- ^gbl2(2,1,4,5)="gbl2_2_1_4_5"
- GTM>
+2 View
+ View
- This example illustrates how MERGE copies a sub-tree of one global into
- another. The nodes in the sub-tree of ^gbl(2), for which $DATA() value is
- 1 or 11, are copied to sub-tree of ^gbl1(1) as follows:
+ The VIEW command adjusts an environmental factor selected by a keyword
+ argument. For example, VIEW controls journal buffer flushing, determines
+ whether GT.M reports undefined variables as errors or treats them as null,
+ and determines which BREAK commands should display messages.
- ^gbl1(1) is updated from the value of ^gbl2(2)
- ^gbl1(1,1,3) is updated from the value of ^gbl2(2,1,3)
- ^gbl1(1,1,4,5) is updated from the value of ^gbl2(2,1,4,5)
+ The format of the VIEW command is:
- Since ^gbl1(2,1) and ^gbl2(2,2,4) do not have values ($DATA()=0), the
- corresponding nodes ^gbl1(1,1) and ^gbl(1,2,4) respectively are left
- unchanged. The naked indicator takes the value ^gbl(1) as if SET replaced
- MERGE. Notice that the MERGE command does not change ^gbl2(2) or its
- descendants. Ancestor nodes of ^gbl(1) are also left unchanged.
+ V[IEW][:tvexpr] keyword[:expr2[:...]][,...]
- Example:
+3 Key_Words
+ Key Words
- GTM>Kill
+4 BREAKMSG
+ BREAKMSG
- GTM>Set ^gbl(1,2)="1,2"
+ "BREAKMSG":value
- GTM>Merge lcl(3,4)=^gbl(1)
+ Sets the value of the BREAK message mask. When GT.M processes a BREAK
+ command, the BREAK message mask controls whether to display a message
+ describing the source of the BREAK.
- GTM>Set ^("naked")=2
+ The mask uses the following four values that are added together to provide
+ the BREAKMSG value.
- GTM>ZWRite ^gbl
- ^gbl(1,2)="1,2"
- ^gbl("naked")=2
- GTM>ZWRite lcl
- lcl(3,4,2)="1,2"
- GTM>
+ 1 - BREAKs within the body of a program
- This example illustrates how MERGE creates a sub-tree of a variable when
- the variable does not exist. Also, notice how the naked indicator is set
- when the source of the MERGE is a global and the destination a local.
+ 2 - BREAKs within a ZBREAK action
-2 New
- New
+ 4 - BREAKs within a device EXCEPTION
- The NEW command "stacks" copies of local variables and reinitializes those
- variables. An explicit or implicit QUIT from a DO, XECUTE or extrinsic
- function "unstacks" the NEWed variables, that is, restores the variable to
- the stacked value. A NEW lasts only while the current scope of execution
- is active.
+ 8 - BREAKs within a ZSTEP action
- The format of the NEW command is:
+ 16 - ZBREAKs within a trigger removed due to updated trigger
+ (TRIGZBREAKREM)
- N[EW][:tvexpr] [[(]lvn[,...][)][,...]]
-
-3 Examples
- Examples
+ The default BREAKMSG mask is 31 (1+2+4+8+16) which means that GT.M
+ displays all BREAK messages.
Example:
- NEW1;
- Set A(1)=1,B=4,C=5
- Write !,"VARIABLES BEFORE NEW:",!
- ZWRite
- Do LABEL
- Write !,"VARIABLES AFTER RETURN:",!
- ZWRite
- Quit
- LABEL
- New A Set C=7
- Write !,"VARIABLES AFTER NEW:",!
- ZWRite
- Quit
-
- Produces the results:
+ GTM>VIEW "BREAKMSG":5
- VARIABLES BEFORE NEW:
- A(1)=1
- B=4
- C=5
- VARIABLES AFTER NEW:
- B=4
- C=7
- VARIABLES AFTER RETURN:
- A(1)=1
- B=4
- C=7
+ In this example the BREAKMSG value is 5, representing the sum of 1 and 4.
+ This enables BREAKS within the body of a program (value 1) and for a
+ device EXCEPTION (value 4).
- Example:
+4 BADCHAR
+ BADCHAR
- NEW2;
- Set (A,B,C,D)="TEST"
- Do LABEL
- Write !,"VARIABLES AFTER RETURN:",!
- ZWRite
- Quit
- LABEL
- New (B,C) SET (A,B,Z)="NEW"
- Write !,"VARIABLES AFTER EXCLUSIVE NEW:",!
- ZWRite
- Quit
+ Enables or disable the gneration of an error when character-oriented
+ functions encounter malformed byte sequences (illegal characters).
- Produces the results:
+ At process startup, GT.M initializes BADCHAR from the environment variable
+ gtm_badchar. Set the environment variable $gtm_badchar to a non-zero
+ number or "YES" (or "Y") to enable VIEW "BADCHAR". Set the environment
+ variable $gtm_badchar to 0 or "NO" or "FALSE" (or "N" or "F") to enable
+ VIEW "NOBADCHAR". By default, GT.M enables VIEW "BADCHAR".
- VARIABLES AFTER EXCLUSIVE NEW:
- A="NEW"
- B="NEW"
- C="TEST"
- Z="NEW"
- VARIABLES AFTER RETURN:
- A="TEST"
- B="NEW"
- C="TEST"
- D="TEST"
+ With VIEW "BADCHAR", GT.M functions generate the BADCHAR error when they
+ encounter malformed byte sequences. With this setting, GT.M detects and
+ clearly reports potential application program logic errors as soon as they
+ appear. As an illegal UTF-8 character in the argument of a
+ character-oriented function likely indicates a logic issue, FIS recommends
+ using VIEW "BADCHAR" in production environments.
- Example:
+ **Note**
- /usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^stackalias
- stackalias ; Demonstrate New with alias
- ZPrint ; Print this program
- Set A=1,*B=A,*C(2)=A ; Create some aliases
- Write "------------",!
- Write "ZWRite in the caller before subprogram",!
- ZWRite
- Do S1 ; Call a subprogram
- Write "------------",!
- Write "ZWRite in the caller after subprogram - A association is restored",!
- ZWRite
- Quit
- ;
- S1 ; Subprogram
- New A
- Set A="I am not an alias",B="I am an alias"
- Write "------------",!
- Write "ZWRite in the subprogram with new A and modified B",!
- ZWRite
- Quit
- ------------
- ZWRite in the caller before subprogram
- A=1 ;*
- *B=A
- C=3
- *C(2)=A
- D=4
- ------------
- ZWRite in the subprogram with new A and modified B
- A="I am not an alias"
- B="I am an alias" ;*
- C=3
- *C(2)=B
- D=4
- ------------
- ZWRite in the caller after subprogram - A association is restored
- A="I am an alias" ;*
- *B=A
- C=3
- *C(2)=A
- D=4
+ When all strings consist of well-formed characters, the value of VIEW
+ [NO]BADCHAR has no effect whatsoever. With VIEW "NOBADCHAR", the same
+ functions treat malformed byte sequences as valid characters. During the
+ migration of an application to add support for Unicode, illegal character
+ errors are likely to be frequent and indicative of application code that
+ is yet to be modified. VIEW "NOBADCHAR" suppresses these errors at times
+ when their presence impedes development.
- The following is essentially the same as the prior example but using an
- exclusive NEW:
+4 DBFLUSH
+ DBFLUSH
+
+ "DBFLUSH"[:REGION[:N]]
+
+ When using the BG access method, writes modified blocks in the global
+ buffers to the database file. By default, this command option operates on
+ all regions under the current global directory. N specifies the number of
+ blocks to write; by default, DBFLUSH writes all modified blocks. Normally
+ GT.M schedules block flushing at appropriate times, but this option exists
+ for an application to explore the impact of flushing on their work load.
+ See also the DBSYNC and EPOCH VIEW Options.
+
+4 DBSYNC
+ DBSYNC
+
+ "DBSYNC":REGION
+
+ Performs a file system hardening sync - fsync() - operation on the
+ database file. By default, this command option operates on all regions
+ under the current global directory. Normally GT.M schedules block flushing
+ at appropriate times, but this option exists for an application to explore
+ the impact of file hardening on their work load. See also the DBFLUSH and
+ EPOCH VIEW Options.
+
+4 DMTERM
+ DMTERM
+
+ Provides a mechanism to retain default line terminators for direct mode
+ user interaction (including the BREAK command) independent of any
+ TERMINATOR deviceparameter changes for $PRINCIPAL. With VIEW "NODMTERM",
+ TERMINATOR deviceparameter apply to both READs from $PRINCIPAL and direct
+ mode interactions. A case-insensitive value of the environment variable
+ gtm_dmterm is "1", "yes", or "true" establishes a NODMTERM state at
+ process initiation; all other values, including no value, result in the
+ default VIEW "NODMTERM" behavior. $VIEW("DMTERM") returns 1 for DMTERM
+ mode or 0 for NODMTERM mode.
+
+4 EPOCH
+ EPOCH
+
+ "EPOCH"[:REGION]
+
+ Flushes the database buffers and, if journaling is enabled, writes an
+ EPOCH record. By default, this command option operates on all regions
+ under the current global directory. Normally GT.M schedules epochs as a
+ user controlled journaling characteristic, but this option exists for an
+ application to explore the impact of epochs on their work load. See also
+ the DBFLUSH and DBSYNC VIEW Options. Epochs include DBFLUSH and DBSYNC
+ actions, but performing them before the epoch may reduce the duration of
+ these actions within the epoch.
+
+4 FULL_BOOLEANWARN
+ FULL_BOOLEANWARN
- $ /usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^stackalias1
- stackalias1 ; Demonstrate New with alias
- ZPrint ; Print this program
- Set A=1,*B=A,*C(2)=A ; Create some aliases
- Write "------------",!
- Write "ZWRite in the caller before subprogram",!
- ZWRite
- Do S1 ; Call a subprogram
- Write "------------",!
- Write "ZWRite in the caller after subprogram - A association is restored",!
- ZWRite
- Quit
- ;
- S1 ; Subprogram
- New (B)
- Set A="I am not an alias",B="I am an alias"
- Write "------------",!
- Write "ZWRite in the subprogram - Notice B is flagged as an alias",!
- ZWRite
- Quit
- ------------
- ZWRite in the caller before subprogram
- A=1 ;*
- *B=A
- C=3
- *C(2)=A
- D=4
- ------------
- ZWRite in the subprogram - Notice B is flagged as an alias
- A="I am not an alias"
- B="I am an alias" ;*
- ------------
- ZWRite in the caller after subprogram - A association is restored
- A="I am an alias" ;*
- *B=A
- C=3
- *C(2)=A
- D=4
+ Controls the evaluation of Boolean expressions (expressions evaluated as a
+ logical TRUE or FALSE).
- An exclusive New can create a scope in which only one association between
- a name or an lvn and an array may be visible. In this case, ZWRITE
- nevertheless shows the existence of an alias, even when that array is
- accessible from only one name or lvn.
+ By default, GT.M enables VIEW "NOFULL_BOOLEAN" which means that GT.M stops
+ evaluating a Boolean expression as soon as it establishes a definitive
+ result. For example, neither 0&$$abc^def() nor 1!$$abc^def() executes
+ $$abc^def(). However, in the case of global references, such as 0&^a or
+ 1!^a, GT.M sets $reference and the naked indicator without actually
+ accessing the global variable.
-2 Open
- Open
+ With VIEW "FULL_BOOLEAN", GT.M ensures that all side effect expression
+ atoms, extrinsic functions ($$), external functions ($&), and $INCREMENT()
+ execute in left-to-right order.
- The OPEN command creates a connection between a GT.M process and a device.
+ With VIEW "FULL_BOOLWARN", GT.M not only evaluates Boolean expressions
+ like "FULL_BOOLEAN" but produces a BOOLSIDEFFECT warning when it
+ encounters Boolean expressions that may induce side-effects; that is:
+ expressions with side effects after the first Boolean operator - extrinsic
+ functions, external calls and $INCREMENT().
- The format of the OPEN command is:
+ GT.M picks up the value of [NO]FULL_BOOL[EAN][WARN] from the environment
+ variable gtm_boolean. If gtm_boolean is undefined or evaluates to an
+ integer zero (0), the initial setting the default "NOFULL_BOOLEAN", if it
+ evaluates to an integer one (1), the initial setting is "FULL_BOOLEAN" and
+ if it evaluates to integer two (2) the initial setting is "FULL_BOOLWARN".
- O[PEN][:tvexpr] expr[:[(keyword[=expr][:...])] [:numexpr]][,...]
+ VIEW "NOFULLBOOLEAN" produces an error when gtm_side_effects is on. For
+ more information on the gtm_side_effects environment variable, refer to
+ the Environment Variables section in the Basic Operations chapter of the
+ Administration and Operations Guide.
-2 Quit
- Quit
+4 GDSCERT
+ GDSCERT
- Except when a QUIT appears on a line after a FOR, the QUIT command
- terminates execution of the current GT.M invocation stack level initiated
- by a DO, XECUTE, extrinsic function or special variable, and return
- control to the next "lower" level. In this case, QUIT restores any values
- stacked at the current level by NEWs or by parameter passing. A QUIT
- command terminates any closest FOR command on the same line. Note that M
- overloads the QUIT command to terminate DO, FOR, XECUTE and extrinsics
- ($$) of which FOR is the most different.
+ Enables (value=1) or disables (value=0) database block certification.
- The format of the QUIT command is:
+ Database block certification causes GT.M to check the internal integrity
+ of every block as it writes the block. Block certification degrades
+ performance and exists primarily as a tool for use by FIS. The default is
+ GDSCERT:0.
- Q[UIT][:tvexpr] [expr]
+4 GVDUPSETNOOP
+ GVDUPSETNOOP
-3 Examples
- Examples
+ Enables (VIEW "GVDUPSETNOOP":1) or disables (VIEW "GVDUPSETNOOP":0)
+ duplication set optimization.
- Example:
+ Duplicate set optimization prevents a SET that does not change the value
+ of an existing node from performing the update or executing any trigger
+ code specified for the node. By default, duplicate set optimization is
+ enabled.
- Do A
- Quit
- A Write !,"This is label A"
+4 JNLFLUSH
+ JNLFLUSH
- The explicit QUIT at the line preceding the label A prevents line A from
- executing twice. The sub-routine at line A terminates with the implicit
- QUIT at the end of the routine.
+ Writes or flushes journaling buffers associated with the given region to
+ permanent storage, for example, to disk. If the VIEW "JNLFLUSH" does not
+ specify the optional region, GT.M flushes all journaled regions of the
+ current Global Directory.
- Example:
+ Normally GT.M writes journal buffers when it completes a transaction
+ (unless TRANSACTIONID="BATCH"), fills the journal buffer or when some
+ period of time passes with no journal activity.
- Write $$ESV
- Quit
- ESV()
- QUIT "value of this Extrinsic Special Variable"
+4 JNLWAIT
+ JNLWAIT
- Because the label ESV has an argument list (which is empty), GT.M can only
- legally reach that label with a extrinsic invocation. The QUIT on the
- second line prevents execution from erroneously "falling through" to the
- line labelled ESV. Because ESV identifies a subroutine that implements an
- extrinsic special variable, the QUIT on the line after ESV has an argument
- to provide the value of the extrinsic.
+ Causes a process to pause until its journaling buffers have been written.
+ JNLWAIT ensures that GT.M successfully transfers all database updates
+ issued by the process to the journal file before the process continues.
+ Normally, GT.M performs journal buffer writes synchronously for TP
+ updates, and asynchronously, while the process continues execution, for
+ non-TP updates or TP updates with TRANSACTIONID=BATCH.
- Example:
+4 JOBPID
+ JOBPID
- Set x="" For Set x=$Order(^BAL(x)) Quit:x]]"AR5999"!'$Length(x) DO STF
+ Enables (value=1) or disables (value=0) the addition of the child process
+ ID to the output and error filenames generated by the JOB command. The
+ default is 0.
- The postconditional QUIT terminates the FOR loop. Note the two spaces
- after the QUIT because it has no argment.
+ The value=1 option prevents output files generated by the JOB command from
+ being overwritten each time a new job is spawned from the GT.M source
+ file.
-2 Read
- Read
+4 LABELS
+ LABELS
- The READ command transfers the input from the current device to a global
- or local variable specified as a READ argument. For convenience, READ also
- accepts arguments that perform limited output to the current device.
+ Enables (value="LOWER") or disables (value="UPPER") case sensitivity for
+ labels within routines.
- The format of the READ command is:
+ It is important to have the same case handling at compile-time and
+ run-time.
- R[EAD][:tvexpr] (glvn|*glvn|glvn#intexpr)[:numexpr]|strlit|fcc[,...]
-
-2 Set
- Set
-
- SET assigns values to variables or to a selected portion of a variable.
-
- The format of the SET command is:
-
- S[ET][:tvexpr] glvn|$EXTRACT()|$PIECE()|(glvn[,...])=expr[,...]
-
- Because GT.M does not require predeclaration or typing of variables, a SET
- withproper syntax always succeeds regardless of the prior state or value
- of the variable, as long as GT.M can evaluate the expression to the right
- of the equal sign (=).
+ Because GT.M stores routines as regular files and file names are case
+ sensitive on UNIX, GT.M always treates routine names as case sensitive.
-3 Examples
- Examples
+4 LINK
+ LINK
- Example:
+ Enables ("LINK":"RECURSIVE") or disables ("LINK":"RECURSIVE") the ZLINK
+ command to accept and relink routines on the GT.M invocation stack. With
+ VIEW "LINK":"RECURSIVE" specified, the ZLINK command adds an executable
+ routine even when a routine with the same name is active and available in
+ the current stack. When a process links a routine with the same name as an
+ existing routine, future calls use the new routine. Prior versions of that
+ routine referenced by the stack remain tied to the stack until they QUIT,
+ at which point they become inaccessible. This provides a mechanism to
+ patch long-running processes.
- GTM>Kill Set a="x",(b,c)=1, at a="hello" ZWRite
- a=x
- b=1
- c=1
- x="hello"
- GTM>
+ The default is VIEW "LINK":"NORECURSIVE".
- The KILL command deletes any previously defined local variables. The SET
- command has three arguments. The first shows a simple direct assignment.
- The second shows the form that assigns the same value to multiple
- variables. The third shows atomic indirection on the left of the equal
- sign. The ZWRITE command displays the results of the assignments.
+4 LOGTPRESTART
+ LOGTPRESTART
- Example:
+ Allows a process to dynamically change the logging of TPRESTART messages
+ to the operator log established at process startup by the environment
+ variables gtm_tprestart_log_delta and gtm_tprestart_log_first.
- GTM>Set ^(3,4)=^X(1,2)
+ VIEW "NOLOGTPRESTART" turns off the logging of TPRESTART messages to the
+ operator log.
- Because GT.M evaluates the right-hand side of the equal sign before the
- left-hand side within a SET argument, the right-hand expression determines
- the naked reference indicator prior to evaluation of the left-hand side.
- Therefore, this example assigns ^X(1,3,4) the value of ^X(1,2).
+ VIEW "LOGTPRESTART"[=intexpr] turns on logging of TPRESTART messages to
+ the operator log. If no intexpr is specified, GT.M uses the value of
+ environment variable gtm_tprestart_log_delta, if it is defined, and one
+ otherwise (that is, every transaction restart will be logged). A negative
+ value of intexpr turns off the logging of TPRESTART messages.
- Example:
+ Note that it is not possible to perform the operations of
+ gtm_tprestart_log_first with VIEW "LOGTPRESTART"[=intexpr].
- GTM>Kill x Set $Piece(x,"^",2)="piece 3" ZWRite x
- x="^^piece 3"
- GTM>
+4 LV_GCOL
+ LV_GCOL
- This SET demonstrates a "set piece" and shows how SET generates missing
- delimiters when required.
+ Starts a data-space garbage collection, which normally happens
+ automatically at appropriate times.
- Example:
+ **Note**
- GTM>Set x="I love hotdogs"
+ There are no visible effects from LV_GCOL, LV_REHASH, and STP_GCOL except
+ for the passage of time depending on the state of your process. FIS uses
+ these VIEW "LV_GCOL","LV_REHASH","STP_GCOL" facilities in testing. They
+ are documented to ensure completeness in product documentation. You may
+ (or may not) find them useful during application development for debugging
+ or performance testing implementation alternatives.
- GTM>Set $Extract(x,3,6)="want"
+4 LV_REHASH
+ LV_REHASH
- GTM>Write x
- I want hotdogs
- GTM>Set $Extract(x,7)=" many "
+ Starts a reorganization of the local variable look-up table, which
+ normally happens automatically at appropriate times.
- GTM>Write x
- I want many hotdogs
- GTM>
+ **Note**
- The SET $EXTRACT command replaces and extracts the specified characters
- with the value of the expression on the right hand side of the equal-sign
- (=).
+ There are no visible effects from LV_REHASH, LV_GCOL, and STP_GCOL except
+ for the passage of time depending on the state of your process. FIS uses
+ these VIEW "LV_GCOL","LV_REHASH","STP_GCOL" facilities in testing. They
+ are documented to ensure completeness in product documentation. You may
+ (or may not) find them useful during application development for debugging
+ or performance testing implementation alternatives.
-2 Set_*
- Set *
+4 NEVERLVNULLSUB
+ NEVERLVNULLSUB
- A SET * command explicitly creates an alias.
+ [NEVER]|[NO]LVNULLSUBS
- The format of a SET * command is:
+ Disallows, partially disallows, or allows local arrays to have empty
+ string subscripts. The default is LVNULLSUBS.
- S[ET][:tvexpr] *lvn|name1=name2[,...]
+ NOLVNULLSUBS disallows any variant of SET to operate on a local array
+ having an empty string subscript.
- Example:
+ NEVERLVNULLSUBS disallows any variant of SET or KILL
+ ($DATA(),$GET(),$ORDER(), and $QUERY()) to operate on a local array having
+ an empty string subscript. An empty string as the last subscript in
+ $ORDER() and $QUERY() has the semantic significance of requesting the next
+ lexical item and is not subject to NULLSUBS errors.
- GTM>ZWRite ; Nothing there
+ LVNULLSUBS allows local arrays to have empty string subscripts.
- GTM>Set *A=B ; Create an association
+ At process startup, GT.M initializes [NEVER][NO]LVNULLSUBS from
+ $gtm_lvnullsubs. Set the environment variable $gtm_lvnullsubsv to:
- GTM>ZWRite ; Still no data to look at
+ **Important**
- GTM>Set A("Malvern")="Pennsylvania" ; Create a node
+ Remember that for global variables, empty string subscript checking is
+ controlled by a database region characteristic. FIS recommends using
+ LVNULLSUBS, NOLVNULLSUBS, or NEVERLVNULLSUBS for local variables and
+ NULLSUBS options ALWAYS or NEVER for global variables.
- GTM>ZWRite ; Now both have values
- A("Malvern")="Pennsylvania"
- *B=A
- GTM>
+4 NOISOLATION
+ NOISOLATION
- Creating an alias container variable not only creates the association but
- also assigns data (the empty string) to the alias container node:
+ where expr must evaluate to one of the following forms
- GTM>ZWRite ; Nothing there
+ * "", that is, the empty string : turn off the feature for all globals
+ for which it has previously been turned on
+ * "^gvn1,^gvn2,..." : turn on the feature for the globals in the list,
+ turning it off for globals for which it has previously been turned on
+ * "+^gvn1,^gvn2,..." : add these globals to the list of globals that
+ have this feature turned on
+ * "-^gvn1,^gvn2,..." : turn off the feature for these globals leaving
+ the status for other globals unchanged
- GTM>Set *C("I am a container")=D
+4 PATCODE
+ PATCODE
- GTM>ZWRite ; Both array for C and association for C("I am a container") are visible
- *C("I am a container")=D
- GTM>Set D=4,D("Jacksonville")="Florida" ; The array for D comes into existence
- GTM>ZWRite ; All is revealed
- *C("I am a container")=D
- D=4 ;*
- D("Jacksonville")="Florida"
- GTM>
+ "PATCODE":"tablename"
- Attempting to create an alias from subscripted lvn that is not an alias
- container variable triggers an error. Continuing the previous example:
+ Identifies the alternative table of unique patterns for use with the "?"
+ operator to be loaded from the pattern definition file. For additional
+ information, refer to the "Internationalization" chapter in the GT.M
+ Programmer's Guide.
- GTM>Set *E=C("I am a container") ; This works because C("I am a container") is a container
+4 PATLOAD
+ PATLOAD
- GTM>Set *F=C(4) ; But this fails because C(4) is not a container
- %GTM-E-UNDEF, Undefined local variable: C(4)
+ Identifies the file containing definitions of unique patterns for use with
+ the "?" operator. These pattern definitions can be used in place of, or in
+ addition to, the standard C, N, U, L, and P.
- GTM>ZWRite E,F ; Note that E has the value originally assigned to D but F remains undefined
- E=4 ;*E("Jacksonville")="Florida"
- %GTM-E-UNDEF, Undefined local variable: F
+4 RCTLDUMP
+ RCTLDUMP
- GTM>
+ Displays the created relinkctl files and the routines looked for in their
+ related directories. An entry in these files does not mean that a given
+ routine was found there. It merely means it was looked for there and shows
+ a cycle number (which ZRUPDATE bumps) whose change indicates a new
+ published version of the given object file. As it is a diagnostic tool for
+ the new feature, FIS may remove or modify this VIEW option in subsequent
+ releases.
-2 TCommit
- TCommit
+4 RESETGVSTATS
+ RESETGVSTATS
- The TCOMMIT command marks the end of a transaction or sub-transaction and
- decrements $TLEVEL. If TCOMMIT marks the end of a transaction (decrements
- $TLEVEL to zero), it invokes a COMMIT, which makes the database updates
- performed by the transaction generally available. A TCOMMIT issued when no
- transaction is in progress ($TLEVEL=0) produces an error.
+ Resets all the process-private global access statistics to 0. This is
+ particularly useful for long running processes which would periodically
+ like to restart the counting without requiring a shut down and restart.
- The format of the TCOMMIT command is:
+4 STP_GCOL
+ STP_GCOL
- TC[OMMIT][:tvexpr]
+ Starts a string-pool garbage collection, which normally happens
+ automatically at appropriate times.
- For an example of the use of the TCOMMIT command, refer to the chapter on
- General Language Features of M in GT.M Programmer's Guide.
+ **Note**
-2 TREstart
- TREstart
+ There are no visible effects from STP_GCOL, LV_GCOL and LV_REHASH except
+ for the passage of time depending on the state of your process. FIS uses
+ these VIEW "LV_GCOL","LV_REHASH","STP_GCOL" facilities in testing. They
+ are documented to ensure completeness in product documentation. You may
+ (or may not) find them useful during application development for debugging
+ or performance testing implementation alternatives.
- The TRESTART command attempts to RESTART the current transaction. A
- RESTART transfers control back to the initial TSTART and restores much of
- the process state to what it was when that TSTART was originally executed.
- A TRESTART issued when no transaction is in progress ($TLEVEL=0) or when
- the transaction does not have RESTART enabled produces an error.
+4 UNDEF
+ UNDEF
- A TRESTART command causes the TP transaction to RESTART in the same way
- that GT.M uses to implicitly restart the transaction in case of resource
- conflicts. All restarts increment the internal transaction retry count to
- a maximum of three (3), at which point, GT.M performs the entire TP
- transaction within a critical section on all databases referenced in the
- transaction.
+ Enables or disables handling of undefined variables as errors. With UNDEF,
+ GT.M handles all references to undefined local or global variables as
+ errors. With NOUNDEF, GT.M handles all references to undefined local or
+ global variables as if the variable had a value of the empty string. In
+ other words, GT.M treats all variables appearing in expressions as if they
+ were the argument of an implicit $GET(). UNDEF is the default.
- GT.M issues a TRESTMAX runtime error when application code attempts a
- TRESTART more than once during a transaction while $TRESTART=4 (note: in
- order to be wholesome, TRESTART usage in application code should always be
- conditional). In the final retry, GT.M holds the critical section lock on
- all databases involved in the transaction. Since a TRESTART cancels all
- the work done in the current transaction and transfers control back to the
- TSTART, limiting the number of times this can be done in the final retry
- limits the time a process can (by virtue of holding a critical section
- lock on the databases) prevent other processes from updating the database.
+ The environment variable $gtm_noundef specifies the initial value value of
+ [NO]UNDEF at process startup. If it is defined, and evaluates to a
+ non-zero integer or any case-independent string or leading substring of
+ "TRUE" or "YES", then GT.M treats undefined variables as having an
+ implicit value of an empty string.
- GT.M limits TP restarts in the final retry due to non-availability of
- M-locks in a similar fashion. GT.M allows a maximum of 16 such restarts
- after which it issues a TPLOCKRESTMAX runtime error.
+ **Note**
- The format for the TRESTART command is:
+ NOUNDEF does not apply to an undefined FOR control variable. This prevents
+ an increment (or decrement) of an undefined FOR control variable from
+ getting into an unintended infinite loop. For example, FOR A=1:1:10 KILL A
+ gives an UNDEF error on the increment from 1 to 2 even with VIEW
+ "NOUNDEF".
- TRE[START][:tvexpr]
+4 TRACE
+ TRACE
- For an example of the use of the TRESTART command, refer to the chapter on
- "General Language Features of M" in the GT.M Programmer's Guide.
+ Traces GT.M program execution and generates profiling information about
+ the lines and functions executed; with low impact on the run-time
+ performance.
-2 TROllback
- TROllback
+ The feature turns on (value=1) or turns off (value=0) M-profiling. This
+ expression must evaluate to a string containing the name of a GT.M global
+ variable. The global may also have subscripts; however the subscripts must
+ be literals or the special variable $JOB.
- The TROLLBACK command terminates a transaction by causing a ROLLBACK,
- which removes all database updates performed within a transaction. A
- TROLLBACK without an argument also sets $TLEVEL and $TRESTART to zero (0).
- Issuing a TROLLBACK when no transaction is in progress ($TLEVEL=0)
- produces an error.
+ The expression is optional when turning M-profiling off, if it exists, it
+ overrides the global variable set when M-profiling was turned on.
- The format of the TROLLBACK command is:
+ gtm_trace_gbl_name enables GT.M tracing at process startup. Setting
+ gtm_trace_gbl_name to a valid global variable name instructs GT.M to
+ report the data in the specified global when a VIEW command disables the
+ tracing, or implicitly at process termination. This setting behaves as if
+ the process issued a VIEW "TRACE" command at process startup. However,
+ gtm_trace_gbl_name has a capability not available with the VIEW command,
+ such that if the environment variable is defined but evaluates to zero (0)
+ or, only on UNIX, to the empty string, GT.M collects the M-profiling data
+ in memory and discards it when the process terminates (this feature is
+ mainly used for in-house testing). Note that having this feature activated
+ for process that otherwise do not open a database file (such as GDE) can
+ cause them to encounter an error.
- TRO[LLBACK][:tvexpr] [intexpr]
+ Example:
- For an example of the use of the TROLLBACK command, refer to the chapter
- on "General Language Features of M" in the GT.M Programmer's Guide.
+ GTM>zprint ^profiling
+ ; In this example, query^profiling, order^profiling, and merge^profling perform the same operation -- store even-numbered subscripts of a global to a subscripted loc
+ al variable. M-profiling results show which yields the fastest execution between the three.
+ profiling
+ kill ^TMP,^trc
+ view "trace":1:"^trc"
+ set ulimit=1500
+ for i=1:1:ulimit set ^TMP(i)=i
+ do qom("^TMP")
+ view "trace":0:"^trc"
+ zwrite ^trc
+ quit
+ qom(y)
+ do query(y)
+ do order(y)
+ do merge(y)
+ quit
+ query(y)
+ new i,qryval
+ set i=0,y=$query(@y)
+ for quit:y="" do
+ . set:i#2 qryval(i)=@y
+ . set y=$query(@y)
+ . set i=i+1
+ quit
+ order(y)
+ new i,ordval
+ set x="",i=0,y=y_"(x)",x=$order(@y)
+ for quit:x="" do
+ . set:i#2 ordval(i)=x
+ . set x=$order(@y)
+ . set i=i+1
+ quit
+ merge(y)
+ new i,merval
+ set i=0,merval=0
+ merge merval=@y
+ for i=1:1:$order(merval(""),-1) do
+ . kill:i#2 merval(i)
+ quit
-2 TStart
- TStart
+ On a Ubuntu system running GTM V6.1-000_x86_64, this example produces an
+ output like the following:
- The TSTART command marks the beginning of a transaction or sub-transaction
- and increments $TLEVEL. When TSTART marks the beginning of a transaction
- ($TLEVEL=1), its arguments determine whether the transaction may RESTART
- and whether serializability is enforced. If a transaction may RESTART, the
- TSTART arguments determine which local variables are restored during a
- RESTART. Serializability is enforced by LOCK commands or, if the SERIAL
- keyword is specified, by GT.M.
+ GTM>do ^profiling
+ ^trc("*CHILDREN")="0:0:0"
+ ^trc("*RUN")="144009:76004:220013"
+ ^trc("profiling","merge")="1:8001:12000:20001:16231"
+ ^trc("profiling","merge",0)="1:0:0:0:5"
+ ^trc("profiling","merge",1)="1:0:0:0:4"
+ ^trc("profiling","merge",2)="1:0:0:0:4"
+ ^trc("profiling","merge",3)="1:8001:0:8001:8044"
+ ^trc("profiling","merge",4)="1:0:12000:12000:7992"
+ ^trc("profiling","merge",4,"FOR_LOOP",1)=1500
+ ^trc("profiling","merge",5)="1500:0:0:0:4"
+ ^trc("profiling","merge",6)="1:0:0:0:174"
+ ^trc("profiling","order")="1:12001:8001:20002:25720"
+ ^trc("profiling","order",0)="1:0:0:0:8"
+ ^trc("profiling","order",1)="1:0:0:0:6"
+ ^trc("profiling","order",2)="1:0:0:0:90"
+ ^trc("profiling","order",3)="1:0:8001:8001:7160"
+ ^trc("profiling","order",3,"FOR_LOOP",1)=1501
+ ^trc("profiling","order",4)="1500:0:0:0:6319"
+ ^trc("profiling","order",5)="1500:12001:0:12001:12069"
+ ^trc("profiling","order",6)="1500:0:0:0:0"
+ ^trc("profiling","order",7)="1:0:0:0:63"
+ ^trc("profiling","profiling",3)="1:0:0:0:9"
+ ^trc("profiling","profiling",4)="1:52003:20001:72004:74499"
+ ^trc("profiling","profiling",4,"FOR_LOOP",1)=1500
+ ^trc("profiling","profiling",5)="1:0:0:0:14"
+ ^trc("profiling","profiling",6)="1:0:0:0:10"
+ ^trc("profiling","qom")="1:0:0:0:78"
+ ^trc("profiling","qom",0)="1:0:0:0:18"
+ ^trc("profiling","qom",1)="1:0:0:0:11"
+ ^trc("profiling","qom",2)="1:0:0:0:9"
+ ^trc("profiling","qom",3)="1:0:0:0:11"
+ ^trc("profiling","qom",4)="1:0:0:0:5"
+ ^trc("profiling","query")="1:72004:20001:92005:88031"
+ ^trc("profiling","query",0)="1:0:0:0:5"
+ ^trc("profiling","query",1)="1:0:0:0:14"
+ ^trc("profiling","query",2)="1:0:0:0:108"
+ ^trc("profiling","query",3)="1:12000:0:12000:7625"
+ ^trc("profiling","query",3,"FOR_LOOP",1)=1501
+ ^trc("profiling","query",4)="1500:8000:0:8000:28256"
+ ^trc("profiling","query",5)="1500:52004:20001:72005:51919"
+ ^trc("profiling","query",6)="1500:0:0:0:0"
+ ^trc("profiling","query",7)="1:0:0:0:85"
+
+ o CPU times are reported in microseconds. 1 second = 1,000,000
+ microseconds.
+ o ^trc("*CHILDREN")="0:0:0" indicates that the main process did not
+ spawn any child process.
+ o ^trc("*RUN")="144009:76004:220013" : the three pieces specify the
+ aggregate User Time, System Time and Total Time values for the main
+ process.
+ o ^trc("profiling","query",3,"FOR_LOOP",1)=1501 specifies the number of
+ times the FOR loop was executed on line #3 of query^profiling.
+ o ^trc("profiling","merge")="1:8001:12000:20001:16231",
+ ^trc("profiling","order")="1:12001:8001:20002:25720",
+ ^trc("profiling","query")="1:72004:20001:92005:88031": the five pieces
+ specify the aggregate Execution Count, User Time, System,Time, Total
+ Time and the Elapsed Time of the code execution for merge^profiling,
+ order^profling, and query^profiling. merge^profiling has the fastest
+ execution time followed by order^profiling. query^profiling is the
+ slowest amongst the three.
+ o ^trc("profiling","merge",3)="1:8001:0:8001:8044" and others like it
+ specifies the cumulative Execution Count, User Time, System Time,
+ Total Time and the Elapsed Time of the code execution of line 3 of
+ merge^profiling.
+ o The M-profiling results are subject to the granularity of the
+ operating system provided time functions. CPU time entries having
+ 0:0:0 values indicate lightweight M mode having 0 to less than 1
+ microsecond.
+
+ Consider the following program that presents the output of this
+ M-profiling result in a tabular report.
+
+ GTM>zprint ^tracereport
+ tracereport(gbl,label,rtn)
+ set gap=15
+ set $piece(x,".",gap*6)="" write x,!
+ write "Line #",?gap,"Count",?gap*2,"User Time",?gap*3,"System Time",?gap*4,"Total Time",?gap*5,"Elapsed Time",!
+ set $piece(x,".",gap*6)="" write x,!
+ for set gbl=$query(@gbl) quit:gbl="" do
+ . if ($length(@gbl,":")=5)&($qsubscript(gbl,1)=rtn)&($qsubscript(gbl,2)=label) do
+ .. set gap=15 set lineno=$qsubscript(gbl,3)
+ .. if lineno="" write label," total",?gap set zp=""
+ .. else write lineno,?gap set zp=label_"+"_lineno_"^"_rtn
+ .. for i=1:1:5 set gap=gap+15 write $piece(@gbl,":",i),?gap
+ .. write !
+ .. set maxlines=$qsubscript(gbl,3)
+ for i=0:1:maxlines do
+ . set zp=label_"+"_i_"^"_rtn
+ . write "Line #",i,": ",?9
+ . zprint @zp
+
+ GTM>do ^tracereport("^trc","order","profiling")
+ .........................................................................................
+ Line # Count User Time System Time Total Time Elapsed Time
+ .........................................................................................
+ order total 1 12001 8001 20002 25720
+ 0 1 0 0 0 8
+ 1 1 0 0 0 6
+ 2 1 0 0 0 90
+ 3 1 0 8001 8001 7160
+ 4 1500 0 0 0 6319
+ 5 1500 12001 0 12001 12069
+ 6 1500 0 0 0 0
+ 7 1 0 0 0 63
+ Line #0: order(y)
+ Line #1: new i,ordval
+ Line #2: set x="",i=0,y=y_"(x)",x=$order(@y)
+ Line #3: for quit:x="" do
+ Line #4: . set:i#2 ordval(i)=x
+ Line #5: . set x=$order(@y)
+ Line #6: . set i=i+1
+ Line #7: quit
+
+ This shows that order^profiling has an elapsed time of 25720 and the
+ maximum elapsed time was on line #5, which was executed 1500 times.
+
+ GTM>do ^tracereport("^trc","merge","profiling")
+ .........................................................................................
+ Line # Count User Time System Time Total Time Elapsed Time
+ .........................................................................................
+ merge total 1 8001 12000 20001 16231
+ 0 1 0 0 0 5
+ 1 1 0 0 0 4
+ 2 1 0 0 0 4
+ 3 1 8001 0 8001 8044
+ 4 1 0 12000 12000 7992
+ 5 1500 0 0 0 4
+ 6 1 0 0 0 174
+ Line #0: merge(y)
+ Line #1: new i,merval
+ Line #2: set i=0,merval=0
+ Line #3: merge merval=@y
+ Line #4: for i=1:1:$order(merval(""),-1) do
+ Line #5: . kill:i#2 merval(i)
+ Line #6: quit
- The format of the TSTART command is:
+ GTM>
- TS[TART][:tvexpr] [([lvn...])|lvn|*|][:keyword|(keyword...)]
+ This shows that merge^profiling has an elapsed time of 16231 and the
+ maximum elapsed time was on line #3, which was executed once.
+
+ Note that M-profiling results are reported for each line. While reporting
+ time for a line containing an invocation of a label, M-profiling excludes
+ the execution time of that label.
+
+ Here is an example:
+
+ GTM>do ^tracereport("^trc","qom","profiling")
+ .........................................................................................
+ Line # Count User Time System Time Total Time Elapsed Time
+ .........................................................................................
+ qom total 1 0 0 0 78
+ 0 1 0 0 0 18
+ 1 1 0 0 0 11
+ 2 1 0 0 0 9
+ 3 1 0 0 0 11
+ 4 1 0 0 0 5
+ Line #0: qom(y)
+ Line #1: do query(y)
+ Line #2: do order(y)
+ Line #3: do merge(y)
+ Line #4: quit
+
+ Notice that the execution of do merge(y) reports an Elapsed Time of 9
+ whereas merge^profiling reported an Elapsed Time of 1149.
+
+ You can write programs like tracereport.m to interpret the results of the
+ M-profiling data and also use them to analyze your code execution path
+ based on your unique requirements.
+
+ view "trace":1: "<gbl>" and view "trace":0: "<gbl>" commands enable and
+ disable M-profiling.
+
+ To perform entryref-specific M-profiling without modifying the source
+ program, use ZBREAK. For example, to perform M-profiling of the entryref
+ merge^profiling, remove VIEW "TRACE" commands from profiling.m and then
+ execute the following commands:
+
+ GTM>ZBREAK merge^profiling:"view ""TRACE"":1:""^mtrc"" write ""Trace"""
+
+ GTM>do ^profiling
+ Trace
+ GTM>view "TRACE":0:"^mtrc"
+
+ GTM>zwrite ^mtrc
+ ^mtrc("*CHILDREN")="0:0:0"
+ ^mtrc("*RUN")="132008:52003:184011"
+ ^mtrc("GTM$DMOD","^")="1:0:0:0:4"
+ ^mtrc("profiling","merge")="1:8001:0:8001:13450"
+ ^mtrc("profiling","merge",1)="1:0:0:0:6"
+ ^mtrc("profiling","merge",2)="1:0:0:0:5"
+ ^mtrc("profiling","merge",3)="1:8001:0:8001:6188"
+ ^mtrc("profiling","merge",4)="1:0:0:0:7149"
+ ^mtrc("profiling","merge",4,"FOR_LOOP",1)=1500
+ ^mtrc("profiling","merge",5)="1500:0:0:0:4"
+ ^mtrc("profiling","merge",6)="1:0:0:0:63"
+ ^mtrc("profiling","profiling")="1:0:0:0:9"
+ ^mtrc("profiling","profiling",8)="1:0:0:0:4"
+ ^mtrc("profiling","qom")="1:0:0:0:9"
+ ^mtrc("profiling","qom",4)="1:0:0:0:4"
- For an example of the TSTART command, refer to the chapter on "General
- Language Features of M" in the GT.M Programmer's Guide.
+ Example:
-3 S[ERIAL]
- S[ERIAL]
+ If prof.m is:
- The SERIAL keyword indicates that GT.M must ensure the serializability of
- the transaction. Note that GT.M always serializes transactions regardless
- of the SERIAL keyword. On a nested TSTART, this portion of the argument is
- irrelevant.
+ prof;
+ set start=1
+ set finish=1000
+ view "TRACE":1:"^trc"
+ kill cycle S max=$$docycle(start,finish,"cycle")
+ view "TRACE":0:"^trc"
+ zwrite ^trc
+ quit
+ ;
+ docycle(first,last,var)
+ new i,currpath,current,maxcycle,n
+ set maxcycle=1
+ for current=first:1:last do cyclehelper
+ quit maxcycle
+ ;
+ cyclehelper
+ set n=current
+ kill currpath
+ for i=0:1 quit:$data(@var@(n))!(1=n) D
+ . set currpath(i)=n
+ . do iterate
+ if 0<i do
+ . if 1=n set i=i+1
+ . else set i=i+ at var@(n)
+ . do updatemax
+ . set n="" for set n=$O(currpath(n)) Q:""=n S @var@(currpath(n))=i-n
+ Q
+ ;
+ iterate
+ if 0=(n#2) set n=n/2
+ else set n=3*n+1
+ quit
+ ;
+ updatemax
+ set:i>maxcycle maxcycle=i
+ quit
+ ;
-3 T[RANSACTIONID]=expr
- T[RANSACTIONID]=expr
+ On executing prof, the output looks like the following (times in the
+ example were chosen for clarity of illustration and are not typical).
- The TRANSACTIONID keyword declares an arbitrary transaction
- identification.
+ ^trc("*CHILDREN")="0:0:0"
+ ^trc("*RUN")="224014:12000:236014"
+ ^trc("prof","cyclehelper")="1000:200013:0:200013:206318"
+ ^trc("prof","cyclehelper",1)="1000:12001:0:12001:3202"
+ ^trc("prof","cyclehelper",2)="1000:0:0:0:3766"
+ ^trc("prof","cyclehelper",3)="1000:64004:0:64004:94215"
+ ^trc("prof","cyclehelper",3,"FOR_LOOP",1)=3227
+ ^trc("prof","cyclehelper",4)="2227:0:0:0:9864"
+ ^trc("prof","cyclehelper",5)="2227:0:0:0:7672"
+ ^trc("prof","cyclehelper",6)="1000:12000:0:12000:3758"
+ ^trc("prof","cyclehelper",7)="432:0:0:0:1520"
+ ^trc("prof","cyclehelper",8)="432:8000:0:8000:11003"
+ ^trc("prof","cyclehelper",9)="432:0:0:0:3298"
+ ^trc("prof","cyclehelper",10)="432:104008:0:104008:61564"
+ ^trc("prof","cyclehelper",10,"FOR_LOOP",1)=2659
+ ^trc("prof","cyclehelper",11)="1000:0:0:0:3424"
+ ^trc("prof","docycle")="1:12001:0:12001:4886"
+ ^trc("prof","docycle",0)="1:0:0:0:83"
+ ^trc("prof","docycle",1)="1:0:0:0:36"
+ ^trc("prof","docycle",2)="1:0:0:0:4"
+ ^trc("prof","docycle",3)="1:12001:0:12001:4706"
+ ^trc("prof","docycle",3,"FOR_LOOP",1)=1000
+ ^trc("prof","docycle",4)="1:0:0:0:1718579845"
+ ^trc("prof","iterate")="2227:12000:12000:24000:30240"
+ ^trc("prof","iterate",1)="2227:0:0:0:8271"
+ ^trc("prof","iterate",2)="2227:12000:0:12000:7727"
+ ^trc("prof","iterate",3)="2227:0:0:0:7658"
+ ^trc("prof","prof",4)="1:0:0:0:22"
+ ^trc("prof","prof",5)="1:0:0:0:8"
+ ^trc("prof","updatemax")="432:0:0:0:4276"
+ ^trc("prof","updatemax",1)="432:0:0:0:1465"
+ ^trc("prof","updatemax",2)="432:0:0:0:1496"
- If TRANSACTIONID="BATCH" or "BA" at transaction completion, the process
- immediately continues execution. When a process issues a [final] TCOMMIT
- for a transaction and journaling is active, by default the process waits
- until the entire transaction is written to the journal file(s) before
- executing the next command. This ensures that every transaction is durable
- before the process moves on to the next step. Transactions flagged as
- "BATCH" have lower latency and higher throughput, but a lower guarantee of
- durability. Normally this flag is used when operational procedures (such
- as a backup) or application code (such as a checkpoint algorithm) provides
- an acceptable alternative means of ensuring durability.
+ Example:
-2 Use
- Use
+ If fortypes.m is:
- The USE command selects the current device for READs (input) and WRITEs
- (output).
+ fortypes;
+ new i,j,k,v
+ set k=1
+ view "TRACE":1:"^trc"
- The format of the USE command is:
+ for i=1:1:3 set v=i
- U[SE][:tvexpr] expr[:(keyword[=expr][:...])][,...]
+ for i=1:1 set v=0 quit:i=3
-2 View
- View
+ for i=1,2:1:4,6 set v=0
- The VIEW command adjusts an environmental factor selected by a keyword
- argument. For example, VIEW controls journal buffer flushing, determines
- whether GT.M reports undefined variables as errors or treats them as null,
- and determines which BREAK commands should display messages.
+ for i=1:1,2 set v=0 quit:i=3
- The format of the VIEW command is:
+ for i=1:1:2 for j=1:1:3 set v=0
- V[IEW][:tvexpr] keyword[:expr2[:...]][,...]
+ for i=1:1:2
+ . for j=1:1:1 do
+ .. set v=0
-3 Key_Words_in_VIEW_Command
- Key Words in VIEW Command
+ set j=5 for i=1:1:j do
+ . set j=(j-1)
-4 "BREAKMSG":value
- "BREAKMSG":value
+ for i=1:1:2 for j=1:1:3 do
+ . set v=0
- Sets the value of the BREAK message mask. When GT.M processes a BREAK
- command, the BREAK message mask controls whether to display a message
- describing the source of the BREAK.
+ for i=1:1:2 do
+ . for j=1:1:3 set v=0
- The mask uses the following four values that are added together to provide
- the BREAKMSG value.
+ for i=1:1:2 do
+ . for j=1:1:3 do
+ .. set v=0
- 1 - BREAKs within the body of a program
+ for i="foo","bar",1:1 set v=0 quit:i=3
- 2 - BREAKs within a ZBREAK action
+ for set k=k+1 quit:k=3
- 4 - BREAKs within a device EXCEPTION
+ for i=1:1:3 for j=1:1:(3-i) set v=0
- 8 - BREAKs within a ZSTEP action
+ for i=1:1:3 for j=1:1:(3-i) for k=1:1:(j+1) set v=0
- By default GT.M displays all BREAK messages.
+ set k=3 view "TRACE":0:"^trc"
+ zwrite ^trc
- Example:
+ quit
- GTM>VIEW "BREAKMSG":5
+ On executing fortypes, the output looks something like the following:
- In this example the BREAKMSG value is 5, representing the sum of 1 and 4.
- This enables BREAKS within the body of a program (value 1) and for a
- device EXCEPTION (value 4).
+ ^trc("*CHILDREN")="4000:0:4000"
+ ^trc("*RUN")="468029:48003:516032"
+ ^trc("fortypes","fortypes",5)="1:0:0:0:9"
+ ^trc("fortypes","fortypes",5,"FOR_LOOP",1)=3
+ ^trc("fortypes","fortypes",7)="1:0:0:0:6"
+ ^trc("fortypes","fortypes",7,"FOR_LOOP",1)=3
+ ^trc("fortypes","fortypes",9)="1:0:0:0:6"
+ ^trc("fortypes","fortypes",9,"FOR_LOOP",1)=5
+ ^trc("fortypes","fortypes",11)="1:0:0:0:6"
+ ^trc("fortypes","fortypes",11,"FOR_LOOP",1)=3
+ ^trc("fortypes","fortypes",13)="1:0:0:0:8"
+ ^trc("fortypes","fortypes",13,"FOR_LOOP",1)=2
+ ^trc("fortypes","fortypes",13,"FOR_LOOP",2)=6
+ ^trc("fortypes","fortypes",15)="1:0:0:0:4"
+ ^trc("fortypes","fortypes",15,"FOR_LOOP",1)=2
+ ^trc("fortypes","fortypes",19)="1:0:0:0:26"
+ ^trc("fortypes","fortypes",19,"FOR_LOOP",1)=5
+ ^trc("fortypes","fortypes",20)="5:0:0:0:4"
+ ^trc("fortypes","fortypes",22)="1:0:0:0:27"
+ ^trc("fortypes","fortypes",22,"FOR_LOOP",1)=2
+ ^trc("fortypes","fortypes",22,"FOR_LOOP",2)=6
+ ^trc("fortypes","fortypes",23)="6:0:0:0:3"
+ ^trc("fortypes","fortypes",25)="1:0:0:0:11"
+ ^trc("fortypes","fortypes",25,"FOR_LOOP",1)=2
+ ^trc("fortypes","fortypes",26)="2:0:0:0:6"
+ ^trc("fortypes","fortypes",26,"FOR_LOOP",1)=6
+ ^trc("fortypes","fortypes",28)="1:0:0:0:8"
+ ^trc("fortypes","fortypes",28,"FOR_LOOP",1)=2
+ ^trc("fortypes","fortypes",29)="2:0:0:0:26"
+ ^trc("fortypes","fortypes",29,"FOR_LOOP",1)=6
+ ^trc("fortypes","fortypes",30)="6:0:0:0:4"
+ ^trc("fortypes","fortypes",32)="1:0:0:0:8"
+ ^trc("fortypes","fortypes",32,"FOR_LOOP",1)=5
+ ^trc("fortypes","fortypes",34)="1:0:0:0:5"
+ ^trc("fortypes","fortypes",34,"FOR_LOOP",1)=2
+ ^trc("fortypes","fortypes",36)="1:0:0:0:8"
+ ^trc("fortypes","fortypes",36,"FOR_LOOP",1)=3
+ ^trc("fortypes","fortypes",36,"FOR_LOOP",2)=3
+ ^trc("fortypes","fortypes",38)="1:0:0:0:14"
+ ^trc("fortypes","fortypes",38,"FOR_LOOP",1)=3
+ ^trc("fortypes","fortypes",38,"FOR_LOOP",2)=3
+ ^trc("fortypes","fortypes",38,"FOR_LOOP",3)=7
-4 [NO]BADCHAR
- [NO]BADCHAR
+4 ZDATE_FORM
+ ZDATE_FORM
- Enables or disable the gneration of an error when character-oriented
- functions encounter malformed byte sequences (illegal characters).
+ Determines whether four digit year code is active for $ZDATE() function.
+ GT.M defaults to zero (0), that is, two digit output.
- At process startup, GT.M initializes BADCHAR from the environment variable
- gtm_badchar. Set the environment variable $gtm_badchar to a non-zero
- number or "YES" (or "Y") to enable VIEW "BADCHAR". Set the environment
- variable $gtm_badchar to 0 or "NO" or "FALSE" (or "N" or "F") to enable
- VIEW "NOBADCHAR". By default, GT.M enables VIEW "BADCHAR".
+ If no value is given with the VIEW command, it turns four digit code on.
+ It is equivalent to the intrinsic special variable $ZDATEFORM. Use
+ $ZDATEFORM to set this VIEW keyword. Also, logical name environment
+ variable gtm_zdate_form may be used to set the initial value to this
+ factor.
- With VIEW "BADCHAR", GT.M functions generate the BADCHAR error when they
- encounter malformed byte sequences. With this setting, GT.M detects and
- clearly reports potential application program logic errors as soon as they
- appear. As an illegal UTF-8 character in the argument of a
- character-oriented function likely indicates a logic issue, FIS recommends
- using VIEW "BADCHAR" in production environments.
+3 Examples
+ Examples
- **Note**
+ Example:
- When all strings consist of well-formed characters, the value of VIEW
- [NO]BADCHAR has no effect whatsoever. With VIEW "NOBADCHAR", the same
- functions treat malformed byte sequences as valid characters. During the
- migration of an application to add support for Unicode, illegal character
- errors are likely to be frequent and indicative of application code that
- is yet to be modified. VIEW "NOBADCHAR" suppresses these errors at times
- when their presence impedes development.
+ GTM>Kill A
-4 [NO]FULL_BOOL[EAN][WARN]
- [NO]FULL_BOOL[EAN][WARN]
+ GTM>View "NOUNDEF"
- Controls the evaluation of Boolean expressions (expressions evaluated as a
- logical TRUE or FALSE).
+ GTM>Write A,?10,$L(A)
+ 0
+ GTM>
- By default, GT.M enables VIEW "NOFULL_BOOLEAN" which means that GT.M stops
- evaluating a Boolean expression as soon as it establishes a definitive
- result. For example, neither 0&$$abc^def() or 1!$$abc^def() ever executes
- $$abc^def(). However, in the case of global references, such as 0&^a or
- 1!^a, GT.M sets $reference and the naked indicator without actually
- accessing the global variable.
+ This demonstrates how a VIEW that specifies NOUNDEF prevents UNDEFined
+ errors.
- With VIEW "FULL_BOOLEAN", GT.M ensures that all side effect expression
- atoms, extrinsic functions ($$), external functions ($&), and $INCREMENT()
- execute in left-to-right order.
+ Example 2:
- With VIEW "FULL_BOOLWARN", GT.M not only evaluates Boolean expressions
- like "FULL_BOOLEAN" but also produces a FULLBOOLWARN warning every time it
- bypasses a short-circuit evaluation. It also produces a BOOLSIDEFFECT
- warning when it encounters Boolean expressions that may induce
- side-effects; that is: expressions with side effects after the first
- Boolean operator - extrinsic functions, external calls and $INCREMENT().
+ GTM>ZLink "NOSENSE"
+ %GTM-E-LABELMISSING Label referenced but
+ not defined:lab
+ %GTM-I-SRCNAM in source module /home/gtmuser1/.fis-gtm/V5.4-002B_x86/r/
+ NOSENSE.m
+ GTM>ZPrint ^NOSENSE
+ NOSENSE;
+ Do lab
+ Quit
+ LAB Write !,"THIS IS NOSENSE"
+ Quit
+ GTM>View "LABELS":"UPPER"
- GT.M picks the value of [NO]FULL_BOOL[EAN][WARN] from the environment
- variable gtm_boolean. If gtm_boolean is undefined or evaluates to an
- integer zero (0), the initial setting the default "NOFULL_BOOLEAN", if it
- evaluates to an integer one (1), the initial setting is "FULL_BOOLEAN" and
- if it evaluates to integer two (2) the initial setting is "FULL_BOOLWARN".
+ GTM>ZLink "NOSENSE.m"
-4 "GDSCERT":value
- "GDSCERT":value
+ GTM>Do ^NOSENSE
+ THIS IS NOSENSE
+ GTM>
- Enables (value=1) or disables (value=0) database block certification.
+ This demonstrates use of VIEW "LABELS" to make label handling case
+ insensitive. Notice that the routine was ZLINKed with an extension of .m
+ to force a recompile and ensure that the object code and the run-time
+ handling of labels is the same.
- Database block certification causes GT.M to check the internal integrity
- of every block as it writes the block. Block certification degrades
- performance and exists primarily as a tool for use by FIS. The default is
- GDSCERT:0.
+2 Write
+ Write
-4 "GVDUPSETNOOP":value
- "GVDUPSETNOOP":value
+ The WRITE command transfers a character stream specified by its arguments
+ to the current device.
- Enables (VIEW "GVDUPSETNOOP":1) or disables (VIEW "GVDUPSETNOOP":0)
- duplication set optimization.
+ The format of the WRITE command is:
- Duplicate set optimization prevents a SET that does not change the value
- of an existing node from performing the update or executing any trigger
- code specified for the node. By default, duplicate set optimization is
- enabled.
+ W[RITE][:tvexpr] expr|*intexpr|fcc[,...]
-4 "JNLFLUSH"[:region]
- "JNLFLUSH"[:region]
+2 Xecute
+ Xecute
- Writes or flushes journaling buffers associated with the given region to
- permanent storage, for example, to disk. If the VIEW "JNLFLUSH" does not
- specify the optional region, GT.M flushes all journaled regions of the
- current Global Directory.
+ The XECUTE command makes an entry in the GT.M invocation stack and
+ executes the argument as GT.M code.
- Normally GT.M writes journal buffers when it completes a transaction
- (unless TRANSACTIONID="BATCH"), fills the journal buffer or when some
- period of time passes with no journal activity.
+ The format of the XECUTE command is:
-4 JNLWAIT
- JNLWAIT
+ X[ECUTE]:tvexpr expr[:tvexpr][,...]
- Causes a process to pause until its journaling buffers have been written.
- JNLWAIT ensures that GT.M successfully transfers all database updates
- issued by the process to the journal file before the process continues.
- Normally, GT.M performs journal buffer writes synchronously for TP
- updates, and asynchronously, while the process continues execution, for
- non-TP updates or TP updates with TRANSACTIONID=BATCH.
+3 Examples
+ Examples
-4 "JOBPID":"value"
- "JOBPID":"value"
+ Example:
- Enables (value=1) or disables (value=0) the addition of the child process
- ID to the output and error filenames generated by the JOB command. The
- default is 0.
+ GTM>Xecute "Write ""HELLO"""
+ HELLO
+ GTM>
- The value=1 option prevents output files generated by the JOB command from
- being overwritten each time a new job is spawned from the GT.M source
- file.
+ This demonstrates a simple use of Xecute.
-4 "LABELS":"value"
- "LABELS":"value"
+ Example:
- Enables (value="LOWER") or disables (value="UPPER") case sensitivity for
- labels within routines.
+ Set x="" For Set x=$Order(^%x(x)) Quit:x="" Xecute x
- It is important to have the same case handling at compile-time and
- run-time.
+ This $ORDER() loop XECUTEs code out of the first level of the global array
+ ^%x. Note that, in most cases, having the code in a GT.M source file, for
+ example TMPX.m, and using a Do ^TMPX improves efficiency.
- Because GT.M stores routines as regular files and file names are case
- sensitive on UNIX, GT.M always treates routine names as case sensitive.
+2 ZAllocate
+ ZAllocate
-4 LV_GCOL
- LV_GCOL
+ The ZALLOCATE command reserves the specified name without releasing
+ previously reserved names. Other GT.M processes cannot reserve the
+ ZALLOCATEd name with a ZALLOCATE or LOCK command.
- Starts a data-space garbage collection, which normally happens
- automatically at appropriate times.
+ The ZALLOCATE command provides compatibility with some other GT.M
+ implementations. The M Development Committee chose to add the + and -
+ delimiters to the LOCK command (incremental locking) rather than adopt the
+ ZALLOCATE and ZDEALLOCATE approach. Therefore, when a design requires an
+ incremental lock mechanism, LOCK +/- has the advantage over ZALLOCATE /
+ ZDEALLOCATE of being part of the M standard. LOCK +/- also has the
+ advantage of working symmetrically when routines using LOCKs are nested.
+ That is, a ZALLOCATE command issued by a process for a named resource
+ already ZALLOCATEd by that process results in no change of state. This
+ means that routines that do ZALLOCATE followed by a ZDEALLOCATE on a named
+ resource that is already ZALLOCATEd by the same process (at routine entry
+ time), will end up ZDEALLOCATEing the named resource (which might not be
+ desired). On the other hand, a LOCK + command issued by a process for a
+ named resource already LOCKed by that process causes the LEVEL of the LOCK
+ to be incremented (as seen in a ZSHOW "L" output). Every LOCK - command on
+ that named resource causes the LEVEL to be decremented. When the LEVEL
+ becomes 0, the named resource is no longer LOCKed.
- **Note**
+ The format of the ZALLOCATE command is:
- There are no visible effects from LV_GCOL, LV_REHASH, and STP_GCOL except
- for the passage of time depending on the state of your process. FIS uses
- these VIEW "LV_GCOL","LV_REHASH","STP_GCOL" facilities in testing. They
- are documented to ensure completeness in product documentation. You may
- (or may not) find them useful during application development for debugging
- or performance testing implementation alternatives.
+ ZA[LLOCATE][:tvexpr] [(]nref[,...][)][:intexpr][,...]
-4 LV_REHASH
- LV_REHASH
+3 Examples
+ Examples
- Starts a reorganization of the local variable look-up table, which
- normally happens automatically at appropriate times.
+ Examples:
- **Note**
+ ZAllocate A
+ ZAllocate ^A
+ ZAllocate ^A(1)
+ ZAllocate (^B("smith"),^C("jones"))
+ ZAllocate @A
- There are no visible effects from LV_REHASH, LV_GCOL, and STP_GCOL except
- for the passage of time depending on the state of your process. FIS uses
- these VIEW "LV_GCOL","LV_REHASH","STP_GCOL" facilities in testing. They
- are documented to ensure completeness in product documentation. You may
- (or may not) find them useful during application development for debugging
- or performance testing implementation alternatives.
+ The first command ZALLOCATEs A; the second, ^A; the third, ^A(1) and the
+ fourth, both ^B("smith") and ^C("jones") simultaneously. The last command
+ ZALLOCATEs the resources named by the value of the variable A.
-4 [NEVER]|[NO]LVNULLSUBS
- [NEVER]|[NO]LVNULLSUBS
+ Example:
- Disallows, partially disallows, or allows local arrays to have empty
- string subscripts. The default is LVNULLSUBS.
+ ZAllocate A,^B, at C
+ ZALLOCATE (A,B,C)
- NOLVNULLSUBS disallows any variant of SET to operate on a local array
- having an empty string subscript.
+ If ZALLOCATE arguments are enclosed in parentheses, the command waits
+ until all names in the argument list become available before reserving any
+ of the names. For example, in the statement ZA (A,B,C), if the resource
+ named C is not available, ZALLOCATE waits until C becomes available before
+ reserving A and B. Using the format illustrated in the first line above,
+ can cause deadlocks because the resource names are reserved as they come
+ available.
- NEVERLVNULLSUBS disallows any variant of SET or KILL
- ($DATA(),$GET(),$ORDER(), and $QUERY()) to operate on a local array having
- an empty string subscript. An empty string as the last subscript in
- $ORDER() and $QUERY() has the semantic significance of requesting the next
- lexical item and is not subject to NULLSUBS errors.
+ When a process attempts to ZALLOCATE a name currently ZALLOCATEd or LOCKed
+ (with the LOCK command) by another process, the ZALLOCATEing process hangs
+ until the other process releases the name. In the event that names remain
+ unavailable for significant periods of time, timeouts allow the process
+ issuing a ZALLOCATE to regain program control.
- LVNULLSUBS allows local arrays to have empty string subscripts.
+ Example:
- At process startup, GT.M initializes [NEVER][NO]LVNULLSUBS from
- $gtm_lvnullsubs. Set the environment variable $gtm_lvnullsubsv to:
+ ZAllocate ^D:5
- **Important**
+ This example specifies a timeout of five seconds. If GT.M reserves ^D
+ before the five seconds elapses, ZALLOCATE sets $TEST to TRUE. If GT.M
+ cannot reserve ^D within the five second timeout, ZALLOCATE sets $TEST to
+ FALSE.
- Remember that for global variables, empty string subscript checking is
- controlled by a database region characteristic. FIS recommends using
- LVNULLSUBS, NOLVNULLSUBS, or NEVERLVNULLSUBS for local variables and
- NULLSUBS options ALWAYS or NEVER for global variables.
+ At the time of ZALLOCATEing a name, no names previously reserved with
+ ZALLOCATE or the LOCK command are released (similarly, LOCKing a name does
+ not release names that have been ZALLOCATEd). For example, after
+ ZALLOCATEing A and LOCKing B, LOCKing B does not release A, and
+ ZALLOCATEing C does not release A or B.
-4 "NOISOLATION":<expr>
- "NOISOLATION":<expr>
+ ZDEALLOCATE releases ZALLOCATED resource names. The ZDEALLOCATE command
+ can only release previously ZALLOCATEd (not LOCKed) names.
- where expr must evaluate to one of the following forms
+ Resource name arguments for LOCKs and ZALLOCATEs intersect. That is, if
+ one process holds a LOCK or ZALLOCATE, another process can neither LOCK
+ nor ZALLOCATE any name falling in the hierarchy of the resource name held
+ by the first process. When a process holds a LOCK or ZALLOCATE, that same
+ process may also LOCK or ZALLOCATE resource names falling in the hierarchy
+ of the currently held resource name. When a single process holds both
+ LOCKs and ZALLOCATEs, a LOCK does not release the ZALLOCATEd resource(s)
+ and a ZDEALLOCATE does not release the LOCKed resource(s).
- * "", that is, the empty string : turn off the feature for all globals
- for which it has previously been turned on
- * "^gvn1,^gvn2,..." : turn on the feature for the globals in the list,
- turning it off for globals for which it has previously been turned on
- * "+^gvn1,^gvn2,..." : add these globals to the list of globals that
- have this feature turned on
- * "-^gvn1,^gvn2,..." : turn off the feature for these globals leaving
- the status for other globals unchanged
+ Example:
-4 "PATCODE":"tablename"
- "PATCODE":"tablename"
+ Lock ^AR(PNT)
+ .
+ .
+ .
+ ZAllocate ^AR(PNT,SUB)
+ .
+ .
+ .
+ Lock ^TOT(TDT)
+ .
+ .
+ ZDEALLOCATE ^AR(PNT,SUB)
- Identifies the alternative table of unique patterns for use with the "?"
- operator to be loaded from the pattern definition file. For additional
- information, refer to the "Internationalization" chapter in the GT.M
- Programmer's Guide.
+2 ZBreak
+ ZBreak
-4 "PATLOAD":"file-specification"
- "PATLOAD":"file-specification"
+ The ZBREAK command sets or clears routine breakpoints during debugging.
- Identifies the file containing definitions of unique patterns for use with
- the "?" operator. These pattern definitions can be used in place of, or in
- addition to, the standard C, N, U, L, and P.
+ The format of the ZBREAK command is:
-4 RESETGVSTATS
- RESETGVSTATS
+ ZB[REAK][:tvexpr] [-]entryref[:[expr][:intexpr]][,...]
- Resets all the process-private global access statistics to 0. This is
- particularly useful for long running processes which would periodically
- like to restart the counting without requiring a shut down and restart.
+3 Examples
+ Examples
-4 STP_GCOL
- STP_GCOL
+ Example:
- Starts a string-pool garbage collection, which normally happens
- automatically at appropriate times.
+ GTM>ZPRint ^ZBTEST
+ ZBTEST;
+ Do SUB
+ Quit
+ SUB Write !,"This is ZBTEST"
+ Quit
+ GTM>ZBREAK SUB^ZBTEST
- **Note**
+ GTM>Do ^ZBTEST
+ %GTM-I-BREAKZBA, Break instruction encountered during ZBREAK action
+ At M source location SUB^ZBTEST
+ GTM>ZSHOW "B"
+ SUB^ZBTEST
- There are no visible effects from STP_GCOL, LV_GCOL and LV_REHASH except
- for the passage of time depending on the state of your process. FIS uses
- these VIEW "LV_GCOL","LV_REHASH","STP_GCOL" facilities in testing. They
- are documented to ensure completeness in product documentation. You may
- (or may not) find them useful during application development for debugging
- or performance testing implementation alternatives.
+ This inserts a ZBREAK with a default action at SUB^ZBTEST. After GT.M
+ encounters the BREAK, the ZSHOW "B" displays this as the only ZBREAK in
+ the image.
-4 [NO]LOGT[PRESTART][=intexpr]
- [NO]LOGT[PRESTART][=intexpr]
+ Example:
- Allows a process to dynamically change the logging of TPRESTART messages
- to the operator log established at process startup by the environment
- variables gtm_tprestart_log_delta and gtm_tprestart_log_first.
+ GTM>ZBREAK -*
- VIEW "NOLOGTPRESTART" turns off the logging of TPRESTART messages to the
- operator log.
-
- VIEW "LOGTPRESTART"[=intexpr] turns on logging of TPRESTART messages to
- the operator log. If no intexpr is specified, GT.M uses the value of
- environment variable gtm_tprestart_log_delta, if it is defined, and one
- otherwise (that is, every transaction restart will be logged). A negative
- value of intexpr turns off the logging of TPRESTART messages.
+ GTM>ZGOTO
- Note that it is not possible to perform the operations of
- gtm_tprestart_log_first with VIEW "LOGTPRESTART"[=intexpr].
+ GTM>ZBREAK SUB^ZBTEST:"W !,""Trace"""
-4 [NO]UNDEF
- [NO]UNDEF
+ GTM>Do ^ZBTEST
+ Trace
+ This is ZBTEST
+ GTM>
- Enables or disables handling of undefined variables as errors. With UNDEF,
- GT.M handles all references to undefined local or global variables as
- errors. With NOUNDEF, GT.M handles all references to undefined local or
- global variables as if the variable had a value of the empty string. In
- other words, GT.M treats all variables appearing in expressions as if they
- were the argument of an implicit $GET(). UNDEF is the default.
+ This removes all existing ZBREAKs with a ZBREAK -*. Note that it is not
+ necessary to remove ZBREAKs before modifying them. It also clears the
+ process invocation stack with an argumentless ZGOTO. Then it uses a ZBREAK
+ to insert a trace-point. Every time GT.M executes the line to where ZBREAK
+ has established a trace-point, it performs the specified action without
+ entering Direct Mode.
- The environment variable $gtm_noundef specifies the initial value value of
- [NO]UNDEF at process startup. If it is defined, and evaluates to a
- non-zero integer or any case-independent string or leading substring of
- "TRUE" or "YES", then GT.M treats undefined variables as having an
- implicit value of an empty string.
+ Example:
- **Note**
+ ZBreak PRINT^TIME::5
- NOUNDEF does not apply to an undefined FOR control variable. This prevents
- an increment (or decrement) of an undefined FOR control variable from
- getting into an unintended infinite loop. For example, FOR A=1:1:10 KILL A
- gives an UNDEF error on the increment from 1 to 2 even with VIEW
- "NOUNDEF".
+ This BREAKs execution at line PRINT in routine just before the fifth time
+ the line is executed.
-4 "TRACE":value:<expr>
- "TRACE":value:<expr>
+ Example:
- Traces GT.M program execution and generates profiling information about
- the lines and functions executed; with low impact on the run-time
- performance.
+ ZBREAK PRINT^TIME:"WRITE AVE BREAK":3
- The feature turns on (value=1) or turns off (value=0) M-profiling. This
- expression must evaluate to a string containing the name of a GT.M global
- variable. The global may also have subscripts; however the subscripts must
- be literals or the special variable $JOB.
+ This inserts a ZBREAK action of WRITE AVE and BREAK before the third
+ execution of PRINT^TIME.
- The expression is optional when turning M-profiling off, if it exists, it
- overrides the global variable set when M-profiling was turned on.
+2 ZCOMpile
+ ZCOMpile
- gtm_trace_gbl_name enables GT.M tracing at process startup. Setting
- gtm_trace_gbl_name to a valid global variable name instructs GT.M to
- report the data in the specified global when a VIEW command disables the
- tracing, or implicitly at process termination. This setting behaves as if
- the process issued a VIEW "TRACE" command at process startup. However,
- gtm_trace_gbl_name has a capability not available with the VIEW command,
- such that if the environment variable is defined but evaluates to zero (0)
- or, only on UNIX, to the empty string, GT.M collects the M-profiling data
- in memory and discards it when the process terminates (this feature is
- mainly used for in-house testing). Note that having this feature activated
- for process that otherwise do not open a database file (such as GDE) can
- cause them to encounter an error.
+ The ZCOMPILE command invokes the GT.M compiler from within the GT.M
+ run-time environment.
- Thus, if the GT.M program lv1.m is:
+ Within GT.M itself, ZCOMPILE provides the functionality of the mumps
+ command, except for mumps -direct.
- lv1 for i=1:1:10 do
- . set l(i)=i
- . do bar
- for i=1:1:5 for j=1:1:4 set lij(i,j)=i+j
- quit
- bar set l(-i)=-i
- quit
+ The format of the ZCOMPILE command is:
- and the program lv2.m is:
+ ZCOM[PILE][:tvexpr] expr[,...]
- lv2 VIEW "TRACE":1:"^lvtr"
- do ^lv1
- VIEW "TRACE":0:"^lvtr"
+ The $ZCSTATUS intrinsic special variable holds the value of the status
+ code for the compilation performed by a ZCOMPILE command.
- zwrite ^lvtr
- quit
+3 Examples
+ Examples
- On executing lv2, the output looks like this (times in the example were
- chosen for clarity of illustration and are not typical):
+ Examples:
- ^lvtr("*CHILDREN")="0:0:0"
- ^lvtr("*RUN")="0:0:0"
- ^lvtr("lv1","bar")="10:8:1:9"
- ^lvtr("lv1","bar",0)="10:5:1:6"
- ^lvtr("lv1","bar",1)="10:3:0:3"
- ^lvtr("lv1","lv1")="1:28:2:30"
- ^lvtr("lv1","lv1",0)="1:8:0:8"
- ^lvtr("lv1","lv1",0,"FOR_LOOP",1)=10
- ^lvtr("lv1","lv1",1)="10:3:1:4"
- ^lvtr("lv1","lv1",2)="10:2:1:3"
- ^lvtr("lv1","lv1",3)="1:15:0:15"
- ^lvtr("lv1","lv1",3,"FOR_LOOP",1)=5
+ ZCOMPILE "EXAMPLE'.m"
- ^lvtr("lv1","lv1",3,"FOR_LOOP",2)=20
- ^lvtr("lv1","lv1",4)="1:0:0:0"
- ^lvtr("lv2","lv2",1)="1:2:0:2"
- ^lvtr("lv2","lv2",2)="1:2:1:3"
+ This compiles EXAMPLE.m in the current working directory.
Example:
- If prof.m is:
+ ZCOMPILE "-list A*.m"
- prof;
- set start=1
- set finish=1000
- view "TRACE":1:"^trc"
- kill cycle S max=$$docycle(start,finish,"cycle")
- view "TRACE":0:"^trc"
- zwrite ^trc
- quit
- ;
- docycle(first,last,var)
- new i,currpath,current,maxcycle,n
- set maxcycle=1
- for current=first:1:last do cyclehelper
- quit maxcycle
- ;
- cyclehelper
- set n=current
- kill currpath
- for i=0:1 quit:$data(@var@(n))!(1=n) D
- . set currpath(i)=n
- . do iterate
- if 0<i do
- . if 1=n set i=i+1
- . else set i=i+ at var@(n)
- . do updatemax
- . set n="" for set n=$O(currpath(n)) Q:""=n S @var@(currpath(n))=i-n
- Q
- ;
- iterate
- if 0=(n#2) set n=n/2
- else set n=3*n+1
- quit
- ;
- updatemax
- set:i>maxcycle maxcycle=i
- quit
- ;
+ This compiles all files starting with a [capital] A and an extension of .m
+ in the current working directory and produces corresponding listing files
+ for each source / object.
- On executing prof, the output looks like the following (times in the
- example were chosen for clarity of illustration and are not typical).
+2 ZContinue
+ ZContinue
- ^trc("*CHILDREN")="0:0:0"
- ^trc("*RUN")="224014:12000:236014"
- ^trc("prof","cyclehelper")="1000:200013:0:200013:206318"
- ^trc("prof","cyclehelper",1)="1000:12001:0:12001:3202"
- ^trc("prof","cyclehelper",2)="1000:0:0:0:3766"
- ^trc("prof","cyclehelper",3)="1000:64004:0:64004:94215"
- ^trc("prof","cyclehelper",3,"FOR_LOOP",1)=3227
- ^trc("prof","cyclehelper",4)="2227:0:0:0:9864"
- ^trc("prof","cyclehelper",5)="2227:0:0:0:7672"
- ^trc("prof","cyclehelper",6)="1000:12000:0:12000:3758"
- ^trc("prof","cyclehelper",7)="432:0:0:0:1520"
- ^trc("prof","cyclehelper",8)="432:8000:0:8000:11003"
- ^trc("prof","cyclehelper",9)="432:0:0:0:3298"
- ^trc("prof","cyclehelper",10)="432:104008:0:104008:61564"
- ^trc("prof","cyclehelper",10,"FOR_LOOP",1)=2659
- ^trc("prof","cyclehelper",11)="1000:0:0:0:3424"
- ^trc("prof","docycle")="1:12001:0:12001:4886"
- ^trc("prof","docycle",0)="1:0:0:0:83"
- ^trc("prof","docycle",1)="1:0:0:0:36"
- ^trc("prof","docycle",2)="1:0:0:0:4"
- ^trc("prof","docycle",3)="1:12001:0:12001:4706"
- ^trc("prof","docycle",3,"FOR_LOOP",1)=1000
- ^trc("prof","docycle",4)="1:0:0:0:1718579845"
- ^trc("prof","iterate")="2227:12000:12000:24000:30240"
- ^trc("prof","iterate",1)="2227:0:0:0:8271"
- ^trc("prof","iterate",2)="2227:12000:0:12000:7727"
- ^trc("prof","iterate",3)="2227:0:0:0:7658"
- ^trc("prof","prof",4)="1:0:0:0:22"
- ^trc("prof","prof",5)="1:0:0:0:8"
- ^trc("prof","updatemax")="432:0:0:0:4276"
- ^trc("prof","updatemax",1)="432:0:0:0:1465"
- ^trc("prof","updatemax",2)="432:0:0:0:1496"
+ The ZCONTINUE command continues routine execution after a BREAK command or
+ a <CTRL-C>.
+
+ The format of the ZCONTINUE command is:
+
+ ZC[ONTINUE][:tvexpr]
+
+2 ZDeallocate
+ ZDeallocate
+
+ The ZDEALLOCATE command releases a specified resource name or names
+ previously reserved by the ZALLOCATE command. The ZDEALLOCATE command
+ releases only the specified name(s) without releasing other names
+ previously reserved with the ZALLOCATE or LOCK command.
+
+ The ZDEALLOCATE command provides compatibility with some other GT.M
+ implementations. The M Development Committee choose to add the + and -
+ delimiters to the LOCK command rather than adopt the ZALLOCATE and
+ ZDEALLOCATE approach. Therefore, when a design requires an incremental
+ lock mechanism, LOCK +/- has the advantage of being part of the M
+ standard. LOCK +/- also has the advantage of working symmetrically when
+ routines using LOCKs are nested.
+
+ The format of the ZDEALLOCATE command is:
+
+ ZD[EALLOCATE][:tvexpr] [nref[,...]]
+
+3 Examples
+ Examples
Example:
- If fortypes.m is:
+2 ZEDit
+ ZEDit
- fortypes;
- new i,j,k,v
- set k=1
- view "TRACE":1:"^trc"
+ The ZEDIT command invokes the editor specified by the EDITOR environment
+ variable for GT.M and opens the specified file for editing. If the EDITOR
+ environment variable is undefined, ZEDIT tries to invoke the UNIX vi
+ editor.
- for i=1:1:3 set v=i
+ By default, ZEDIT puts a new file into the first source directory in
+ $ZROUTINES. You can specify a file path explicitly in the argument to the
+ ZEDIT command, for example: the current working directory:
- for i=1:1 set v=0 quit:i=3
+ ZEDIT "./file"
- for i=1,2:1:4,6 set v=0
+ The format of the ZEDIT command is:
- for i=1:1,2 set v=0 quit:i=3
+ ZED[IT][:tvexpr] [expr[,...]]
- for i=1:1:2 for j=1:1:3 set v=0
+ When the argument to a ZEDIT includes a file or path name, $ZSOURCE
+ maintains that as a default for ZEDIT and ZLINK.
- for i=1:1:2
- . for j=1:1:1 do
- .. set v=0
+3 Examples
+ Examples
- set j=5 for i=1:1:j do
- . set j=(j-1)
+ Example:
- for i=1:1:2 for j=1:1:3 do
- . set v=0
+ GTM>ZEDIT "BAL"
- for i=1:1:2 do
- . for j=1:1:3 set v=0
+ This invokes the editor for a file with a name of BAL and an extension of
+ .m. Notice that BAL is a string literal.
- for i=1:1:2 do
- . for j=1:1:3 do
- .. set v=0
+ Example:
- for i="foo","bar",1:1 set v=0 quit:i=3
+ GTM>Set prog="BAL"
- for set k=k+1 quit:k=3
+ GTM>ZEDit prog
- for i=1:1:3 for j=1:1:(3-i) set v=0
+ This is similar to the first example except that it uses a variable
+ argument rather than a string literal.
- for i=1:1:3 for j=1:1:(3-i) for k=1:1:(j+1) set v=0
+ Example:
- set k=3 view "TRACE":0:"^trc"
- zwrite ^trc
+ GTM>zedit ".login"
- quit
+ This invokes the editor for a file with the name .login. Notice that in
+ this case the file is not a GT.M file, since .login starts with a period,
+ and therefore, cannot be a GT.M file.
- On executing fortypes, the output looks something like the following:
+2 ZGoto
+ ZGoto
- ^trc("*CHILDREN")="4000:0:4000"
- ^trc("*RUN")="468029:48003:516032"
- ^trc("fortypes","fortypes",5)="1:0:0:0:9"
- ^trc("fortypes","fortypes",5,"FOR_LOOP",1)=3
- ^trc("fortypes","fortypes",7)="1:0:0:0:6"
- ^trc("fortypes","fortypes",7,"FOR_LOOP",1)=3
- ^trc("fortypes","fortypes",9)="1:0:0:0:6"
- ^trc("fortypes","fortypes",9,"FOR_LOOP",1)=5
- ^trc("fortypes","fortypes",11)="1:0:0:0:6"
- ^trc("fortypes","fortypes",11,"FOR_LOOP",1)=3
- ^trc("fortypes","fortypes",13)="1:0:0:0:8"
- ^trc("fortypes","fortypes",13,"FOR_LOOP",1)=2
- ^trc("fortypes","fortypes",13,"FOR_LOOP",2)=6
- ^trc("fortypes","fortypes",15)="1:0:0:0:4"
- ^trc("fortypes","fortypes",15,"FOR_LOOP",1)=2
- ^trc("fortypes","fortypes",19)="1:0:0:0:26"
- ^trc("fortypes","fortypes",19,"FOR_LOOP",1)=5
- ^trc("fortypes","fortypes",20)="5:0:0:0:4"
- ^trc("fortypes","fortypes",22)="1:0:0:0:27"
- ^trc("fortypes","fortypes",22,"FOR_LOOP",1)=2
- ^trc("fortypes","fortypes",22,"FOR_LOOP",2)=6
- ^trc("fortypes","fortypes",23)="6:0:0:0:3"
- ^trc("fortypes","fortypes",25)="1:0:0:0:11"
- ^trc("fortypes","fortypes",25,"FOR_LOOP",1)=2
- ^trc("fortypes","fortypes",26)="2:0:0:0:6"
- ^trc("fortypes","fortypes",26,"FOR_LOOP",1)=6
- ^trc("fortypes","fortypes",28)="1:0:0:0:8"
- ^trc("fortypes","fortypes",28,"FOR_LOOP",1)=2
- ^trc("fortypes","fortypes",29)="2:0:0:0:26"
- ^trc("fortypes","fortypes",29,"FOR_LOOP",1)=6
- ^trc("fortypes","fortypes",30)="6:0:0:0:4"
- ^trc("fortypes","fortypes",32)="1:0:0:0:8"
- ^trc("fortypes","fortypes",32,"FOR_LOOP",1)=5
- ^trc("fortypes","fortypes",34)="1:0:0:0:5"
- ^trc("fortypes","fortypes",34,"FOR_LOOP",1)=2
- ^trc("fortypes","fortypes",36)="1:0:0:0:8"
- ^trc("fortypes","fortypes",36,"FOR_LOOP",1)=3
- ^trc("fortypes","fortypes",36,"FOR_LOOP",2)=3
- ^trc("fortypes","fortypes",38)="1:0:0:0:14"
- ^trc("fortypes","fortypes",38,"FOR_LOOP",1)=3
- ^trc("fortypes","fortypes",38,"FOR_LOOP",2)=3
- ^trc("fortypes","fortypes",38,"FOR_LOOP",3)=7
-
-4 "ZDATE_FORM":"value"
- "ZDATE_FORM":"value"
+ The ZGOTO command transfers control to various levels in the GT.M
+ invocation stack. It also can transfer control from one part of the
+ routine to another or from one routine to another using the specified
+ entryref.
- Determines whether four digit year code is active for $ZDATE() function.
- GT.M defaults to zero (0), that is, two digit output.
+ The format of the ZGOTO command is:
- If no value is given with the VIEW command, it turns four digit code on.
- It is equivalent to the intrinsic special variable $ZDATEFORM. Use
- $ZDATEFORM to set this VIEW keyword. Also, logical name environment
- variable gtm_zdate_form may be used to set the initial value to this
- factor.
+ ZG[OTO][:tvexpr] [[intexpr][:entryref[:tvexpr]],...]
3 Examples
Examples
Example:
- GTM>Kill A
-
- GTM>View "NOUNDEF"
-
- GTM>Write A,?10,$L(A)
- 0
- GTM>
-
- This demonstrates how a VIEW that specifies NOUNDEF prevents UNDEFined
- errors.
-
- Example 2:
-
- GTM>ZLink "NOSENSE"
- %GTM-E-LABELMISSING Label referenced but
- not defined:lab
- %GTM-I-SRCNAM in source module /home/gtmuser1/.fis-gtm/V5.4-002B_x86/r/
- NOSENSE.m
- GTM>ZPrint ^NOSENSE
- NOSENSE;
- Do lab
- Quit
- LAB Write !,"THIS IS NOSENSE"
- Quit
- GTM>View "LABELS":"UPPER"
-
- GTM>ZLink "NOSENSE.m"
+ GTM>ZGOTO
- GTM>Do ^NOSENSE
- THIS IS NOSENSE
+ GTM>ZSHow
+ +1^GTM$DMOD (Direct mode)
GTM>
- This demonstrates use of VIEW "LABELS" to make label handling case
- insensitive. Notice that the routine was ZLINKed with an extension of .m
- to force a recompile and ensure that the object code and the run-time
- handling of labels is the same.
-
-2 Write
- Write
+ This uses ZGOTO to clear all levels of the GT.M invocation stack. ZSHOW
+ with no arguments displays the stack.
- The WRITE command transfers a character stream specified by its arguments
- to the current device.
+ Example:
- The format of the WRITE command is:
+ SET $ZTRAP="ZGOTO "_$ZLEVEL_":^ERROR"
- W[RITE][:tvexpr] expr|*intexpr|fcc[,...]
+ This SETs $ZTRAP to contain a ZGOTO, so if an error causes GT.M to XECUTE
+ $ZTRAP, the routine ERROR executes at the same level as the SET command
+ shown in the example.
-2 Xecute
- Xecute
+2 ZHALT
+ ZHALT
- The XECUTE command makes an entry in the GT.M invocation stack and
- executes the argument as GT.M code.
+ The ZHALT command stops program execution and causes GT.M to return
+ control to the invoking environment/program with a return code.
- The format of the XECUTE command is:
+ The format of the ZHALT command is:
- X[ECUTE]:tvexpr expr[:tvexpr][,...]
+ ZHALT[:tvexpr] [intexpr]
3 Examples
Examples
Example:
- GTM>Xecute "Write ""HELLO"""
- HELLO
- GTM>
-
- This demonstrates a simple use of Xecute.
+ GTM>zhalt 230
+ $ echo $?
+ 230
Example:
- Set x="" For Set x=$Order(^%x(x)) Quit:x="" Xecute x
-
- This $ORDER() loop XECUTEs code out of the first level of the global array
- ^%x. Note that, in most cases, having the code in a GT.M source file, for
- example TMPX.m, and using a Do ^TMPX improves efficiency.
-
-2 ZAllocate
- ZAllocate
+ GTM>zhalt 257
+ $ echo $?
+ 1
- The ZALLOCATE command reserves the specified name without releasing
- previously reserved names. Other GT.M processes cannot reserve the
- ZALLOCATEd name with a ZALLOCATE or LOCK command.
+2 ZHelp
+ ZHelp
- The ZALLOCATE command provides compatibility with some other GT.M
- implementations. The M Development Committee chose to add the + and -
- delimiters to the LOCK command (incremental locking) rather than adopt the
- ZALLOCATE and ZDEALLOCATE approach. Therefore, when a design requires an
- incremental lock mechanism, LOCK +/- has the advantage over ZALLOCATE /
- ZDEALLOCATE of being part of the M standard. LOCK +/- also has the
- advantage of working symmetrically when routines using LOCKs are nested.
- That is, a ZALLOCATE command issued by a process for a named resource
- already ZALLOCATEd by that process results in no change of state. This
- means that routines that do ZALLOCATE followed by a ZDEALLOCATE on a named
- resource that is already ZALLOCATEd by the same process (at routine entry
- time), will end up ZDEALLOCATEing the named resource (which might not be
- desired). On the other hand, a LOCK + command issued by a process for a
- named resource already LOCKed by that process causes the LEVEL of the LOCK
- to be incremented (as seen in a ZSHOW "L" output). Every LOCK - command on
- that named resource causes the LEVEL to be decremented. When the LEVEL
- becomes 0, the named resource is no longer LOCKed.
+ The ZHELP command accesses the help information from the GTM help library
+ or from any help library specified in the command argument.
- The format of the ZALLOCATE command is:
+ The format of the ZHELP command is:
- ZA[LLOCATE][:tvexpr] [(]nref[,...][)][:intexpr][,...]
+ ZH[ELP][:tvexpr] [expr1[:expr2],...]
3 Examples
Examples
- Examples:
+ Example:
- ZAllocate A
- ZAllocate ^A
- ZAllocate ^A(1)
- ZAllocate (^B("smith"),^C("jones"))
- ZAllocate @A
+ GTM>zhelp "func $data"
- The first command ZALLOCATEs A; the second, ^A; the third, ^A(1) and the
- fourth, both ^B("smith") and ^C("jones") simultaneously. The last command
- ZALLOCATEs the resources named by the value of the variable A.
+ This lists the help for function $DATA, which is a subtopic of functions
+ topic.
Example:
- ZAllocate A,^B, at C
- ZALLOCATE (A,B,C)
-
- If ZALLOCATE arguments are enclosed in parentheses, the command waits
- until all names in the argument list become available before reserving any
- of the names. For example, in the statement ZA (A,B,C), if the resource
- named C is not available, ZALLOCATE waits until C becomes available before
- reserving A and B. Using the format illustrated in the first line above,
- can cause deadlocks because the resource names are reserved as they come
- available.
+ GTM>zhelp
- When a process attempts to ZALLOCATE a name currently ZALLOCATEd or LOCKed
- (with the LOCK command) by another process, the ZALLOCATEing process hangs
- until the other process releases the name. In the event that names remain
- unavailable for significant periods of time, timeouts allow the process
- issuing a ZALLOCATE to regain program control.
+ This uses ZHELP to list all the keywords in the help library.
Example:
- ZAllocate ^D:5
+ GTM>zhelp "ZSHOW"
- This example specifies a timeout of five seconds. If GT.M reserves ^D
- before the five seconds elapses, ZALLOCATE sets $TEST to TRUE. If GT.M
- cannot reserve ^D within the five second timeout, ZALLOCATE sets $TEST to
- FALSE.
+ This lists the help for command ZSHOW.
- At the time of ZALLOCATEing a name, no names previously reserved with
- ZALLOCATE or the LOCK command are released (similarly, LOCKing a name does
- not release names that have been ZALLOCATEd). For example, after
- ZALLOCATEing A and LOCKing B, LOCKing B does not release A, and
- ZALLOCATEing C does not release A or B.
+2 ZLink
+ ZLink
- ZDEALLOCATE releases ZALLOCATED resource names. The ZDEALLOCATE command
- can only release previously ZALLOCATEd (not LOCKed) names.
+ The ZLINK command adds an executable GT.M routine to the current process
+ if the current process does not contain a copy of a routine. If the
+ current process contains a copy of a routine and the routine is not
+ active, the ZLINK command replaces the current routine process with a
+ "new" version. If necessary, the ZLINK command compiles the routine prior
+ to integrating it with the process.
- Resource name arguments for LOCKs and ZALLOCATEs intersect. That is, if
- one process holds a LOCK or ZALLOCATE, another process can neither LOCK
- nor ZALLOCATE any name falling in the hierarchy of the resource name held
- by the first process. When a process holds a LOCK or ZALLOCATE, that same
- process may also LOCK or ZALLOCATE resource names falling in the hierarchy
- of the currently held resource name. When a single process holds both
- LOCKs and ZALLOCATEs, a LOCK does not release the ZALLOCATEd resource(s)
- and a ZDEALLOCATE does not release the LOCKed resource(s).
+ With VIEW "LINK":"RECURSIVE" specified or by starting the process with the
+ environment variable gtm_link set to "RECURSIVE", the ZLINK command adds
+ an executable routine even when a routine with the same name is active and
+ available in the current stack. When a process links a routine with the
+ same name as an existing routine, future calls use the new routine. Prior
+ versions of that routine referenced by the stack remain tied to the stack
+ until they QUIT, at which point they become inaccessible. This provides a
+ mechanism to patch long-running processes.
- Example:
+ **Important**
- Lock ^AR(PNT)
- .
- .
- .
- ZAllocate ^AR(PNT,SUB)
- .
- .
- .
- Lock ^TOT(TDT)
- .
- .
- ZDEALLOCATE ^AR(PNT,SUB)
+ An active routine is displayed with $STACK() or ZSHOW "S" of the M virtual
+ stack. By default, an attempt to replace an active routine results in a
+ run-time error . To replace an active routine with a new version, either
+ use VIEW "LINK":"RECURSIVE" or remove the active routine from the stack
+ using ZGOTO or the appropriate number of QUITs and then execute the ZLINK
+ command.
-2 ZBreak
- ZBreak
+ The format of the ZLINK command is:
- The ZBREAK command sets or clears routine breakpoints during debugging.
+ ZL[INK][:tvexpr] [expr1[:expr2][,...]]
- The format of the ZBREAK command is:
+3 ZLINK_Compilation
+ ZLINK Compilation
- ZB[REAK][:tvexpr] [-]entryref[:[expr][:intexpr]][,...]
+ If ZLINK compiles a routine and the -OBJECT= qualifier does not redirect
+ the output, it places the resulting object file in the directory indicated
+ by the search criteria. ZLINK incorporates the new object file into the
+ image, regardless of its directory placement.
+
+ If the command does not specify compile qualifiers (with expr2) and
+ $ZCOMPILE is null, GT.M uses the default M command qualifiers, -ignore,
+ -labels=lower, -nolist, and -object.
3 Examples
Examples
Example:
- GTM>ZPRint ^ZBTEST
- ZBTEST;
- Do SUB
- Quit
- SUB Write !,"This is ZBTEST"
- Quit
- GTM>ZBREAK SUB^ZBTEST
+ GTM>ZLINK "test"
- GTM>Do ^ZBTEST
- %GTM-I-BREAKZBA, Break instruction encountered during ZBREAK action
- At M source location SUB^ZBTEST
- GTM>ZSHOW "B"
- SUB^ZBTEST
+ If ZLINK finds test.m or test.o, it adds the routine test to the current
+ image. If ZLINK does not find test.o, or finds that test.o is older than
+ test.m, GT.M compiles test.m to produce a new test.o, and adds the
+ contents of the new object file to the image. This example assumes "test"
+ is not on the current M stack - if it is on the stack, GT.M gives an
+ error.
- This inserts a ZBREAK with a default action at SUB^ZBTEST. After GT.M
- encounters the BREAK, the ZSHOW "B" displays this as the only ZBREAK in
- the image.
+ Example:
+
+ GTM>zlink "test.m":"-noobject -list"
+
+ This compiles the routine "test" and produces a listing but no object
+ file. Because the example produces no object file, it must locate an
+ existing object file (which might be the same as any copy in the current
+ image); if there is noexisting object file, GT.M produces an error. While
+ this example shows the use of compilation qualifiers with ZLINK, a
+ -noobject -list compilation might better be done with ZCOMPILE.
Example:
- GTM>ZBREAK -*
+ GTM>zlink "sockexamplemulti2"
+ %GTM-E-LOADRUNNING, Cannot ZLINK an active routine sockexamplemulti2
- GTM>ZGOTO
+ GTM>zshow "S"
+ sockexamplemulti2+12^sockexamplemulti2 (Direct mode)
- GTM>ZBREAK SUB^ZBTEST:"W !,""Trace"""
+ GTM>view "LINK":"RECURSIVE"
- GTM>Do ^ZBTEST
- Trace
- This is ZBTEST
- GTM>
+ GTM>zlink "sockexamplemulti2"
- This removes all existing ZBREAKs with a ZBREAK -*. Note that it is not
- necessary to remove ZBREAKs before modifying them. It also clears the
- process invocation stack with an argumentless ZGOTO. Then it uses a ZBREAK
- to insert a trace-point. Every time GT.M executes the line to where ZBREAK
- has established a trace-point, it performs the specified action without
- entering Direct Mode.
+ GTM>
- Example:
+ This example demonstrates how VIEW "LINK":"RECURSIVE" command ZLINKs a
+ routine when its prior version is already there in the active M virtual
+ stack.
- ZBreak PRINT^TIME::5
+3 Auto-ZLINK
+ Auto-ZLINK
- This BREAKs execution at line PRINT in routine just before the fifth time
- the line is executed.
+ If a GT.M routine refers to a routine that is not linked in the process
+ memory, GT.M automatically attempts to ZLINK that routine. An auto-ZLINK
+ is functionally equivalent to an explicit ZLINK of a routine without a
+ specified directory or file extension.
- Example:
+ The following GT.M commands and functions can initiate auto-ZLINKing:
- ZBREAK PRINT^TIME:"WRITE AVE BREAK":3
+ * DO
+ * GOTO
+ * ZBREAK
+ * ZGOTO
+ * ZPRINT
+ * $TEXT()
- This inserts a ZBREAK action of WRITE AVE and BREAK before the third
- execution of PRINT^TIME.
+ GT.M auto-ZLINKs the routine if the following conditions are met:
-2 ZCOMpile
- ZCOMpile
+ * ZLINK can locate and process the routine file, as indicated in the
+ previous ZLINK Operation Summary table
+ * The name of the routine is the same as the name of the source file;
+ the only exception is that GT.M converts a leading percent sign (%) in
+ a file name to an underscore (_).
- The ZCOMPILE command invokes the GT.M compiler from within the GT.M
- run-time environment.
+3 Auto-ZLINK_setup
+ Auto-ZLINK setup
+
+ This section describes the procedure to setup the field test grade
+ auto-relink functionality that is available in V6.2-000. Although V6.2-000
+ when used without auto-relink (i.e., without use of the ZRUPDATE command
+ or the special syntax in $ZROUTINES) is a generally available, production
+ grade release, use auto-relink only in development and test environments
+ where field test grade functionality is acceptable.
+
+ By suffixing one or more directory names in $ZROUTINES with a single
+ asterisk (*), processes can subscribe to updates of object files published
+ in those directories. At the invocation of DO, GOTO, or ZGOTO, extrinsic
+ functions, $TEXT(), or ZPRINT that specify an entryref which includes a
+ routine name (vs. a label without a routine name), mumps processes (and
+ mupip processes executing trigger logic) automatically relink
+ ("auto-relink") and execute published new versions of routines.
+
+ o Label references (that is , without a routine name), whether direct or
+ through indirection, always refer to the current routine, and do not
+ invoke auto-relink logic.
+ o Use shell quoting rules when appending asterisks to directory names in
+ the gtmroutines environment variable - asterisks must be passed in to
+ GT.M, and not expanded by the shell.
+ o GT.M accepts but ignores asterisk suffixes to directory names on
+ 32-bit Linux on x86 platforms, where it does not provide
+ auto-relinking.
+
+ The ZRUPDATE command publishes of new versions of routines to subscribers.
+ To remove routines, delete the object files and publish the names of the
+ deleted object files. Removal requires file names to be explicitly
+ specified, because patterns with wildcards cannot match deleted files.
+
+ If the path to a file is non-existent, the request is ignored except in
+ the case where one desires a currently shared object file (one that was
+ accessed before it was deleted) to no longer be shared. In V6.2-000, if
+ the process executing the ZRUPDATE does not have read permission to any
+ directory in the path to a file, ZRUPDATE ignores the request; FIS expect
+ to correct this in the production release.
+
+ To effect auto-relink, GT.M creates small temporary files in the directory
+ referred to by $gtm_linktmpdir (defaulting to $gtm_tmp, which in turn
+ defaults to /tmp, if unspecified). The names of these files are of the
+ form gtm-relinkctl-<md5sum> where <md5sum> is a hash of the realpath() to
+ an auto-relink directory. In the field test software, the permissions are
+ determined by the umask of the process creating a file. In the production
+ software, FIS intends for the group and permissions to match those for
+ shared resources as described in the section Shared Resources
+ Authorization Permissions in Appendix E (GT.M Security Philosophy) of the
+ UNIX Administration and Operations Guide. FIS recommends that all
+ processes that share a directory whose contents are subject to ZRUPDATE
+ use the same value for $gtm_linktmpdir so that all processes see update
+ notifications - with different values of $gtm_linktmpdir, a ZRUPDATE by a
+ process with one value of $gtm_linktmpdir would not be observed by a
+ process with a different value of that environment variable.
+
+ When a process that has subscribed to updates to routines in a directory
+ links to a routine from that directory, it maps the object file to its
+ address space, sharing the object code with other processes that are so
+ subscribed, and without requiring the object code to be placed in a shared
+ library. Processes that have not subscribed to updates link using
+ process-private heap space as they have in prior versions.
+
+ AIX has known architectural limitations to scalability when large numbers
+ of processes (thousands to tens of thousands) auto-relink large numbers of
+ routines (again thousands to tens of thousands of routines). In the
+ typical case where the number of dynamically modified routines is much
+ smaller than the total number of routines in an enterprise scale
+ application, a scalable way for large applications to use auto-relinking
+ on AIX is to place all routines in shared libraries, and define $ZROUTINES
+ with an auto-relink enabled patch directory preceding the shared library.
+ Scalability on HP-UX and Solaris is not known: FIS is not aware of any
+ inherent scalability issues other than those imposed by available hardware
+ resources when the product of the number of processes and the number of
+ auto-relinked remains well below the number of file descriptors made
+ available by the OS.
+
+ Changing $ZROUTINES currently causes all routines linked from
+ auto-relink-enabled directories in the process to be re-linked. FIS
+ intends for this to generate an error in the production release.
+
+ VIEW "RCTLDUMP" displays the created relinkctl files and the routines
+ looked for in their related directories. An entry in these files does not
+ mean that a given routine was found there. It merely means it was looked
+ for there and shows a cycle number (which ZRUPDATE bumps) whose change
+ indicates a new published version of the given object file. As it is a
+ diagnostic tool for the new feature, FIS may remove or modify this VIEW
+ option in subsequent releases.
- Within GT.M itself, ZCOMPILE provides the functionality of the mumps
- command, except for mumps -direct.
+3 ZLINK,_auto-ZLINK_and_Routine_Names
+ ZLINK, auto-ZLINK and Routine Names
- The format of the ZCOMPILE command is:
+ In GT.M, the name of the source file determines the name of the GT.M
+ routine. The file name of the object file is not required to match the
+ name of the routine. Linking the object file makes the internal routine
+ name (derived from the source file) known to GT.M. This can lead to
+ potential confusion, however, since both ZLINK and auto-ZLINK use the name
+ of the object file to find the routine. When the object file name differs
+ from the name of the routine, auto-ZLINK generates a run-time error.
- ZCOM[PILE][:tvexpr] expr[,...]
+ **Note**
- The $ZCSTATUS intrinsic special variable holds the value of the status
- code for the compilation performed by a ZCOMPILE command.
+ Auto-ZLINK and ZLINK commands without a .m or .o file extension in their
+ argument determine the need to recompile based on whether the object file
+ was more recently modified than the source file using time in nanoseconds,
+ as provided by the underlying system call. Note that, although the format
+ of the file modification timestamps provides a nanosecond granularity,
+ many supported OSs currently update the file timestamps with an accuracy
+ of one second.
-3 Examples
- Examples
+2 ZKill
+ ZKill
- Examples:
+ The ZKILL command KILLs the data value for a variable name without
+ affecting the nodes descended from that node.
- ZCOMPILE "EXAMPLE'.m"
+ The format of the ZKILL command is:
- This compiles EXAMPLE.m in the current working directory.
+ ZK[ILL][:tvexpr] glvn
- Example:
+2 ZMessage
+ ZMessage
- ZCOMPILE "-list A*.m"
+ The ZMESSAGE command raises an exception condition based on the specified
+ message code.
- This compiles all files starting with a [capital] A and an extension of .m
- in the current working directory and produces corresponding listing files
- for each source / object.
+ The format of the ZMESSAGE command is:
-2 ZContinue
- ZContinue
+ ZM[ESSAGE][:tvexpr] intexpr[:expr2][:...]
- The ZCONTINUE command continues routine execution after a BREAK command or
- a <CTRL-C>.
+3 Examples
+ Examples
- The format of the ZCONTINUE command is:
+ All of the following examples issue ZMESSAGE from Direct Mode where
+ exception conditions do not invoke $ZTRAP.
- ZC[ONTINUE][:tvexpr]
+ Example:
-2 ZDeallocate
- ZDeallocate
+ GTM>ZMessage 2
- The ZDEALLOCATE command releases a specified resource name or names
- previously reserved by the ZALLOCATE command. The ZDEALLOCATE command
- releases only the specified name(s) without releasing other names
- previously reserved with the ZALLOCATE or LOCK command.
+ %SYSTEM-E-ENO2, No such file or directory
- The ZDEALLOCATE command provides compatibility with some other GT.M
- implementations. The M Development Committee choose to add the + and -
- delimiters to the LOCK command rather than adopt the ZALLOCATE and
- ZDEALLOCATE approach. Therefore, when a design requires an incremental
- lock mechanism, LOCK +/- has the advantage of being part of the M
- standard. LOCK +/- also has the advantage of working symmetrically when
- routines using LOCKs are nested.
+ This ZMESSAGE does not specify substitution text and the message does not
+ include any substitution directives.
- The format of the ZDEALLOCATE command is:
+ Example:
- ZD[EALLOCATE][:tvexpr] [nref[,...]]
+ GTM>ZMESSAGE 150372994
+ %GTM-E-GVUNDEF, Global Variable undefined:
-3 Examples
- Examples
+ The message specified by this ZMESSAGE command includes a substitution
+ directive but the command does not supply any text.
Example:
-2 ZEDit
- ZEDit
+ GTM>ZMESSAGE 150373850:"x"
+ %GTM-E-GVUNDEF, Undefined local variable: x
- The ZEDIT command invokes the editor specified by the EDITOR environment
- variable for GT.M and opens the specified file for editing. If the EDITOR
- environment variable is undefined, ZEDIT tries to invoke the UNIX vi
- editor.
+ This ZMESSAGE command supplies the substitution text for the message.
- By default, ZEDIT puts a new file into the first source directory in
- $ZROUTINES. You can specify a file path explicitly in the argument to the
- ZEDIT command, for example: the current working directory:
+ GT.M treats its own odd-numbered conditions as "successful." GT.M handles
+ successful conditions by displaying the associated message and continuing
+ execution. GT.M treats its own even-numbered conditions as failures. GT.M
+ handles failure conditions by storing the error information in $ZSTATUS
+ and XECUTEing $ETRAP or $ZTRAP In Direct Mode, GT.M only reports failure
+ conditions to the principal device and does not XECUTE $ETRAP or $ZTRAP or
+ set $ZSTATUS. System service errors do not follow the GT.M odd/even
+ pattern.
- ZEDIT "./file"
+2 ZPrint
+ ZPrint
- The format of the ZEDIT command is:
+ The ZPRINT command displays the source code lines selected by its
+ argument.
- ZED[IT][:tvexpr] [expr[,...]]
+ The format of the ZPRINT command is:
- When the argument to a ZEDIT includes a file or path name, $ZSOURCE
- maintains that as a default for ZEDIT and ZLINK.
+ ZP[RINT][:tvexpr][entryref[:label[+intexpr]][,...]
+
+ Note that the routinename may only appear before the colon (:) delimiter.
+ The integer expression offsets may be positive or negative, but they must
+ always be delimited by a plus sign (+).
3 Examples
Examples
Example:
- GTM>ZEDIT "BAL"
+ GTM>ZPRINT X^RTN
- This invokes the editor for a file with a name of BAL and an extension of
- .m. Notice that BAL is a string literal.
+ This example displays the line beginning with the label X in the routine
+ RTN.
Example:
- GTM>Set prog="BAL"
+ GTM>ZPRINT X^RTN:X+5
- GTM>ZEDit prog
+ GTM>ZPRINT X+-5^RTN:X
- This is similar to the first example except that it uses a variable
- argument rather than a string literal.
+ GTM>ZPRINT X^RTN:X+-5^RTN
+
+ The first line displays the line beginning with the label X and the next 5
+ lines in routine RTN. The second line displays the 5 lines preceding label
+ X in the same routine and the line beginning with label X. The third line
+ generates a run-time error because the routine name must appear only
+ before the colon in the argument.
Example:
- GTM>zedit ".login"
+ GTM>zprint ^A#1#
+ do ^test1
+ do stop^test2
+ GTM>
- This invokes the editor for a file with the name .login. Notice that in
- this case the file is not a GT.M file, since .login starts with a period,
- and therefore, cannot be a GT.M file.
+ This command displays the trigger code for trigger name A#1#.
-2 ZGoto
- ZGoto
+2 ZRUPDATE
+ ZRUPDATE
+
+ Publishes the new versions of routines to subscribers. THe format of the
+ ZRUPDATE command is:
+
+ ZRUP[DATE][:tvexpr] expr [,...]
+
+ o The optional truth-valued expression immediately following the command
+ is a command postconditional that controls whether or not GT.M
+ executes the command.
+ o expr contains a object file names, with or without wildcards, for
+ which ZRUPDATE attempts to publish the new version of routines to
+ subscribers.
+ o To remove routines, delete the object files and publish the names of
+ the deleted object files. Removal requires file names to be explicitly
+ specified, because patterns with wildcards cannot match deleted files.
+ o If the path to a file is non-existent, the request is ignored except
+ in the case where one desires a currently shared object file (one that
+ was accessed before it was deleted) to no longer be shared. In
+ V6.2-000, if the process executing the ZRUPDATE does not have read
+ permission to any directory in the path to a file, ZRUPDATE ignores
+ the request; FIS expects to correct this in the production release.
+ o To effect auto-relink, GT.M creates small temporary files in the
+ directory referred to by $gtm_linktmpdir (defaulting to $gtm_tmp,
+ which in turn defaults to /tmp, if unspecified). The names of these
+ files are of the form gtm-relinkctl<md5sum> where <md5sum> is a hash
+ of the realpath() to an auto-relink directory. In the field test
+ software, the permissions are determined by the umask of the process
+ creating a file. In the production software, FIS intends for the group
+ and permissions to match those for shared resources as described in
+ the section Shared Resources Authorization Permissions in Appendix E
+ (GT.M Security Philosophy) of the UNIX Administration and Operations
+ Guide. FIS recommends that all processes that share a directory whose
+ contents are subject to ZRUPDATE use the same value for
+ $gtm_linktmpdir so that all processes see update notifications - with
+ different values of $gtm_linktmpdir, a ZRUPDATE by a process with one
+ value of $gtm_linktmpdir would not be observed by a process with a
+ different value of that environment variable.
- The ZGOTO command transfers control to various levels in the GT.M
- invocation stack. It also can transfer control from one part of the
- routine to another or from one routine to another using the specified
- entryref.
+2 ZSHow
+ ZSHow
- The format of the ZGOTO command is:
+ The ZSHOW command displays information about the current GT.M environment.
- ZG[OTO][:tvexpr] [[intexpr][:entryref[:tvexpr]],...]
+ The format of the ZSHOW command is:
-3 Examples
- Examples
+ ZSH[OW][:tvexpr][expr[:glvn][,...]]
- Example:
+3 ZSHOW_Information_Codes
+ ZSHOW Information Codes
- GTM>ZGOTO
+ A ZSHOW argument is an expression containing codes selecting one or more
+ types of information.
- GTM>ZSHow
- +1^GTM$DMOD (Direct mode)
- GTM>
+ B: displays active ZBREAK breakpoints
- This uses ZGOTO to clear all levels of the GT.M invocation stack. ZSHOW
- with no arguments displays the stack.
+ D: displays device information
- Example:
+ G: displays the access statistics for global variables and access to
+ database file since process startup
- SET $ZTRAP="ZGOTO "_$ZLEVEL_":^ERROR"
+ I: displays the current values of all intrinsic special variables
- This SETs $ZTRAP to contain a ZGOTO, so if an error causes GT.M to XECUTE
- $ZTRAP, the routine ERROR executes at the same level as the SET command
- shown in the example.
+ L: displays GT.M LOCKs and ZALLOCATEs held by the process
-2 ZHelp
- ZHelp
+ R: displays the GT.M invocation stack and an MD5 checksum of M source code
+ for each routine on the stack.
- The ZHELP command accesses the help information from the GTM help library
- or from any help library specified in the command argument.
+ S: displays the GT.M invocation stack
- The format of the ZHELP command is:
-
- ZH[ELP][:tvexpr] [expr1[:expr2],...]
-
-3 Examples
- Examples
-
- Example:
-
- GTM>zhelp "func $data"
-
- This lists the help for function $DATA, which is a subtopic of functions
- topic.
-
- Example:
-
- GTM>zhelp
-
- This uses ZHELP to list all the keywords in the help library.
-
- Example:
-
- GTM>zhelp "ZSHOW"
-
- This lists the help for command ZSHOW.
-
-2 ZLink
- ZLink
-
- The ZLINK command adds an executable GT.M routine to the current process
- if the current process does not contain a copy of a routine. If the
- current process contains a copy of a routine and the routine is not
- active, the ZLINK command replaces the current routine process with a
- "new" version. If necessary, the ZLINK command compiles the routine prior
- to integrating it with the process.
-
- **Important**
-
- An active routine is displayed with $STACK() or ZSHOW "S. of the M virtual
- stack. An attempt to replace an active routine results in a run-time error
- because changing a routine in progress could have unpredictable results.
- To replace an active routine with a new version, first remove the active
- routine from the stack using ZGOTO or the appropriate number of QUITs and
- then execute the ZLINK command.
-
- The format of the ZLINK command is:
-
- ZL[INK][:tvexpr] [expr1[:expr2][,...]]
-
-3 ZLINK_Compilation
- ZLINK Compilation
-
- If ZLINK compiles a routine and the -OBJECT= qualifier does not redirect
- the output, it places the resulting object file in the directory indicated
- by the search criteria. ZLINK incorporates the new object file into the
- image, regardless of its directory placement.
-
- If the command does not specify compile qualifiers (with expr2) and
- $ZCOMPILE is null, GT.M uses the default M command qualifiers, -ignore,
- -labels=lower, -nolist, and -object.
-
-3 Examples
- Examples
-
- Example:
-
- GTM>ZLINK "test"
-
- If ZLINK finds test.m or test.o, it adds the routine test to the current
- image. If ZLINK does not find test.o, or finds that test.o is older than
- test.m, GT.M compiles test.m to produce a new test.o, and adds the
- contents of the new object file to the image. This example assumes "test"
- is not on the current M stack - if it is on the stack, GT.M gives an
- error.
-
- Example:
-
- GTM>zlink "test.m":"-noobject -list"
-
- This compiles the routine "test" and produces a listing but no object
- file. Because the example produces no object file, it must locate an
- existing object file (which might be the same as any copy in the current
- image); if there is noexisting object file, GT.M produces an error. While
- this example shows the use of compilation qualifiers with ZLINK, a
- -noobject -list compilation might better be done with ZCOMPILE.
-
-3 Auto-ZLINK
- Auto-ZLINK
-
- If a GT.M routine refers to a routine that is not linked to the GT.M
- image, GT.M automatically attempts to ZLINK that routine. An auto-ZLINK is
- functionally equivalent to an explicit ZLINK of a routine without a
- specified directory or file extension.
-
- The following GT.M commands and functions can initiate auto-ZLINKing:
-
- * DO
- * GOTO
- * ZBREAK
- * ZGOTO
- * ZPRINT
- * $TEXT()
-
- GT.M auto-ZLINKs the routine if the following conditions are met:
-
- * ZLINK can locate and process the routine file, as indicated in the
- previous ZLINK Operation Summary table
- * The name of the routine is the same as the name of the source file;
- the only exception is that GT.M converts a leading percent sign (%) in
- a file name to an underscore (_).
-
-3 ZLINK,_auto-ZLINK_and_Routine_Names
- ZLINK, auto-ZLINK and Routine Names
-
- In GT.M, the name of the source file determines the name of the GT.M
- routine. The file name of the object file is not required to match the
- name of the routine. Linking the object file makes the internal routine
- name (derived from the source file) known to GT.M. This can lead to
- potential confusion, however, since both ZLINK and auto-ZLINK use the name
- of the object file to find the routine. When the object file name differs
- from the name of the routine, auto-ZLINK generates a run-time error.
-
-2 ZKill
- ZKill
-
- The ZKILL command KILLs the data value for a variable name without
- affecting the nodes descended from that node.
-
- The format of the ZKILL command is:
-
- ZK[ILL][:tvexpr] glvn
-
-2 ZMessage
- ZMessage
-
- The ZMESSAGE command raises an exception condition based on the specified
- message code.
-
- The format of the ZMESSAGE command is:
-
- ZM[ESSAGE][:tvexpr] intexpr[:expr2][:...]
-
-3 Examples
- Examples
-
- All of the following examples issue ZMESSAGE from Direct Mode where
- exception conditions do not invoke $ZTRAP.
-
- Example:
-
- GTM>ZMessage 2
-
- %SYSTEM-E-ENO2, No such file or directory
-
- This ZMESSAGE does not specify substitution text and the message does not
- include any substitution directives.
-
- Example:
-
- GTM>ZMESSAGE 150372994
- %GTM-E-GVUNDEF, Global Variable undefined:
-
- The message specified by this ZMESSAGE command includes a substitution
- directive but the command does not supply any text.
-
- Example:
-
- GTM>ZMESSAGE 150373850:"x"
- %GTM-E-GVUNDEF, Undefined local variable: x
-
- This ZMESSAGE command supplies the substitution text for the message.
-
- GT.M treats its own odd-numbered conditions as "successful." GT.M handles
- successful conditions by displaying the associated message and continuing
- execution. GT.M treats its own even-numbered conditions as failures. GT.M
- handles failure conditions by storing the error information in $ZSTATUS
- and XECUTEing $ETRAP or $ZTRAP In Direct Mode, GT.M only reports failure
- conditions to the principal device and does not XECUTE $ETRAP or $ZTRAP or
- set $ZSTATUS. System service errors do not follow the GT.M odd/even
- pattern.
-
-2 ZPrint
- ZPrint
-
- The ZPRINT command displays the source code lines selected by its
- argument.
-
- The format of the ZPRINT command is:
-
- ZP[RINT][:tvexpr][entryref[:label[+intexpr]][,...]
-
- Note that the routinename may only appear before the colon (:) delimiter.
- The integer expression offsets may be positive or negative, but they must
- always be delimited by a plus sign (+).
-
-3 Examples
- Examples
-
- Example:
-
- GTM>ZPRINT X^RTN
-
- This example displays the line beginning with the label X in the routine
- RTN.
-
- Example:
-
- GTM>ZPRINT X^RTN:X+5
-
- GTM>ZPRINT X+-5^RTN:X
-
- GTM>ZPRINT X^RTN:X+-5^RTN
-
- The first line displays the line beginning with the label X and the next 5
- lines in routine RTN. The second line displays the 5 lines preceding label
- X in the same routine and the line beginning with label X. The third line
- generates a run-time error because the routine name must appear only
- before the colon in the argument.
-
- Example:
-
- GTM>zprint ^A#1#
- do ^test1
- do stop^test2
- GTM>
-
- This command displays the trigger code for trigger name A#1#.
-
-2 ZSHow
- ZSHow
-
- The ZSHOW command displays information about the current GT.M environment.
-
- The format of the ZSHOW command is:
-
- ZSH[OW][:tvexpr][expr[:glvn][,...]]
-
-3 ZSHOW_Information_Codes
- ZSHOW Information Codes
-
- A ZSHOW argument is an expression containing codes selecting one or more
- types of information.
-
- B: displays active ZBREAK breakpoints
-
- C: displays available external call table entry names
-
- D: displays device information
-
- G: displays the access statistics for global variables and access to
- database file since process startup
-
- I: displays the current values of all intrinsic special variables
-
- L: displays GT.M LOCKs and ZALLOCATEs held by the process
-
- S: displays the GT.M invocation stack
-
- V: displays local and alias variables
+ V: displays local and alias variables
* displays all possible types of ZSHOW information
@@ -6525,7 +6493,7 @@
in the results of the "V" code.
If the wildcard (*) occurs in the list, ZSHOW uses the default order
- (ZSHOW "IVBDLGSC" ):
+ (ZSHOW "IVBDLGR" ):
If G occurs in the list, the statistics are displayed in the following
order in a comma-separated list where each item has its mnemonic followed
@@ -7136,33 +7104,8 @@
A=1 ;*
*B=A
-2 ZHALT
- ZHALT
-
- The ZHALT command stops program execution and causes GT.M to return
- control to the invoking environment/program with a return code.
-
- The format of the ZHALT command is:
-
- ZHALT[:tvexpr] [intexpr]
-
-3 Examples
- Examples
-
- Example:
-
- GTM>zhalt 230
- $ echo $?
- 230
-
- Example:
-
- GTM>zhalt 257
- $ echo $?
- 1
-
-1 Functions
- Functions
+1 Functions
+ Functions
This chapter describes M language Intrinsic Functions implemented in GT.M.
Traditional string processing functions have parallel functions that start
@@ -8477,221 +8420,154 @@
3 Argument_Keywords_of_$VIEW()
Argument Keywords of $VIEW()
- $VIEW() provides a means of accessing GT.M environmental information.
- $VIEW() is similar in purpose to Intrinsic Special Variables. When GT.M
- permits modification of the factors accessible with $VIEW(), the VIEW
- command generally provides the tool for performing the change.
-
- +------------------------------------------------------------------------+
- | $VIEW() Argument Keywords |
- |------------------------------------------------------------------------|
- | ARG 1 | ARG 2 | RETURN VALUE |
- |-------------------+----------------+-----------------------------------|
- | "BREAKMSG" | none | Value of the break message mask; |
- | | | GT.M defaults this to 31. |
- |-------------------+----------------+-----------------------------------|
- | "FREEBLOCKS" | region | Number of free database blocks in |
- | | | a given region. |
- |-------------------+----------------+-----------------------------------|
- | | | Process-id of the process that |
- | | | has frozen the database |
- | | | associated with the region |
- | "FREEZE" | region | specified (using DSE or MUPIP). |
- | | | |
- | | | If the region is currently not |
- | | | frozen, returns a value of 0. |
- |-------------------+----------------+-----------------------------------|
- | | | Truth Value indicating whether |
- | | | Database block certification is |
- | | | currently enabled or disabled. |
- | "GDSCERT" | none | |
- | | | To enable or disable Database |
- | | | block certification, use the VIEW |
- | | | "GDSCERT" command. |
- |-------------------+----------------+-----------------------------------|
- | "GVACCESS_METHOD" | region | Access method of the region. |
- |-------------------+----------------+-----------------------------------|
- | "GVFILE" | region | Name of the database associated |
- | | | with the region. |
- |-------------------+----------------+-----------------------------------|
- | | | Name of the first database region |
- | "GVFIRST" | none | in the current global directory. |
- | | | Is functionally equivalent to |
- | | | $VIEW("GVNEXT","") |
- |-------------------+----------------+-----------------------------------|
- | | | Name of the next database region |
- | "GVNEXT" | region | after the given one; "" for |
- | | | region starts with the first |
- | | | region. |
- |-------------------+----------------+-----------------------------------|
- | | | Encoded information about |
- | | | database behavior since segment |
- | | | creation. It also includes SET |
- | | | operations even if they are |
- | | | inside a TP transaction. |
- | | | |
- | | | If you require completely |
- | | | accurate GVSTATS, you need to |
- | "GVSTAT" | region | ensure the last process to close |
- | | | a database always has write |
- | | | access to the database files. If |
- | | | read-only processes are the |
- | | | active processes in a database, |
- | | | they cannot update the database |
- | | | and may delete the shared memory |
- | | | where they have stored the counts |
- | | | of their actions (for examples |
- | | | blocks read). |
- |-------------------+----------------+-----------------------------------|
- | "ICHITS" | none | Number of indirection cache hits |
- | | | since GT.M image activation. |
- |-------------------+----------------+-----------------------------------|
- | | | Number of indirection cache |
- | "ICMISS" | none | misses since GT.M image |
- | | | activation. |
- |-------------------+----------------+-----------------------------------|
- | | | can return the following values: |
- | | | |
- | | | * -1 (internal error) |
- | "JNLACTIVE" | region | * 0 journaling is disabled |
- | | | * 1 journaling is enabled but |
- | | | closed (OFF) |
- | | | * 2 journaling is enabled and |
- | | | open (ON) |
- |-------------------+----------------+-----------------------------------|
- | "JNLFILE" | region | Journal file name associated with |
- | | | the region. |
- |-------------------+----------------+-----------------------------------|
- | | | Index showing how many ZTSTART |
- | "JNLTRANSACTION" | none | transaction fences have been |
- | | | opened (and not closed). |
- |-------------------+----------------+-----------------------------------|
- | | | Truth value showing whether label |
- | "LABELS" | none | case sensitivity is ON (1 for |
- | | | "LOWER") or OFF (0 for "UPPER"); |
- | | | GT.M defaults to 1. |
- |-------------------+----------------+-----------------------------------|
- | | | returns the number of references |
- | | | by alias containers to the array |
- | | | associated with an unsubscripted |
- | "LV_CREF" | local variable | local variable name specified as |
- | | name (lvn) | a second expr (for example a |
- | | | quoted string); it returns a zero |
- | | | for a variable without any |
- | | | associated alias container. |
- |-------------------+----------------+-----------------------------------|
- | | | returns the number of data-spaces |
- | | | recovered during a local variable |
- | "LV_GCOL" | none | data-space garbage collection it |
- | | | triggers; such collections |
- | | | normally happen automatically at |
- | | | appropriate times. |
- |-------------------+----------------+-----------------------------------|
- | | | returns the total number of |
- | | | references to the data-space |
- | "LV_REF" | local variable | associated with an unsubscripted |
- | | name (lvn) | local variable name specified as |
- | | | a second expr (for example a |
- | | | quoted string). |
- |-------------------+----------------+-----------------------------------|
- | | | Truth value showing whether null |
- | | | subscripts are permitted in local |
- | "LVNULLSUBS" | none | arrays (1 for "LVNULLSUBS") or |
- | | | not (o for "NOLVNULLSUBS"); GT.M |
- | | | defaults to 1. |
- |-------------------+----------------+-----------------------------------|
- | | | The current isolation-status of |
- | | | the specified global variable |
- | | | which must have a leading "^" in |
- | | | its specification. |
- | | | |
- | | | This function returns 1 if the |
- | | | global has isolation turned off |
- | | | (that is, noisolation turned on) |
- | "NOISOLATION" | global | and 0 otherwise. |
- | | | |
- | | | By default, all globals will have |
- | | | isolation turned on, that is, a |
- | | | $VIEW command will return 0. The |
- | | | isolation-status of a global |
- | | | |
- | | | variable can be turned on and off |
- | | | by the VIEW "NOISOLATION" |
- | | | command. |
- |-------------------+----------------+-----------------------------------|
- | "REGION" | gvn | Name of the region holding the |
- | | | given global name. |
- |-------------------+----------------+-----------------------------------|
- | "PATCODE" | none | Name of the active patcode table; |
- | | | GT.M defaults this to "M". |
- |-------------------+----------------+-----------------------------------|
- | | | Name of the next routine in the |
- | | | image after the given one; "" |
- | "RTNNEXT" | routine name | (empty string) for routinename |
- | | | starts with the first routine in |
- | | | ASCII collating sequence. |
- |-------------------+----------------+-----------------------------------|
- | | | Number of bytes in the currently |
- | | | allocated as process working |
- | | | storage. GT.M manages this space |
- | | | as what is commonly called a |
- | | | heap, and uses the term |
- | "SPSIZE" | none | stringpool to refer to it. The |
- | | | GT.M garbage collector reclaims |
- | | | unused space from the stringpool |
- | | | from time to time, and GT.M |
- | | | automatically expands the |
- | | | stringpool as needed by the |
- | | | application program. |
- |-------------------+----------------+-----------------------------------|
- | | | Returns the GT.M stack size in |
- | | | bytes. In VMS, the GT.M stack |
- | "STKSIZ" | none | size is user settable at image |
- | | | startup time by means of the |
- | | | USER_STACK_SIZE parameter in |
- | | | GTM$DEFAULTS.M64. |
- |-------------------+----------------+-----------------------------------|
- | "TOTALBLOCKS" | region | Total number of database blocks |
- | | | in a given region. |
- |-------------------+----------------+-----------------------------------|
- | | | Transaction ID specified in the |
- | | | particular level (when the |
- | | | transaction level is specified). |
- | | NULL | The first level TSTART is |
- | | | returned if the level is not |
- | | or | specified as second argument. |
- | "TRANSACTIONID" | | |
- | | transaction | **Note** |
- | | level | |
- | | | A NULL string is returned if the |
- | | | specified level (explicitly or |
- | | | implicitly) is greater than the |
- | | | current value of $TLEVEL. |
- |-------------------+----------------+-----------------------------------|
- | | | Truth value showing whether |
- | | | undefined variables should be |
- | "UNDEF" | none | treated as having a null value (1 |
- | | | for "UNDEF"; 0 for "NOUNDEF"); |
- | | | GT.M defaults to 0. |
- |-------------------+----------------+-----------------------------------|
- | | | Integer value showing whether |
- | | | four digit year code is active |
- | | | for $ZDATE(); GT.M defaults to 0 |
- | "ZDATE_FORM" | none | (for "YY" format). Use the |
- | | | environment variable |
- | | | gtm_zdate_form to set the initial |
- | | | value of this factor. |
- |-------------------+----------------+-----------------------------------|
- | | | Truth value showing whether ISV |
- | | | $ZDIR stores the whole path |
- | | | (including device specification) |
- | | | or just the directory path (0 for |
- | "ZDIR_FORM" | none | $ZDIR storing device |
- | | | specification and directory path; |
- | | | 1 for $ZDIR storing only the |
- | | | directory path); GT.M defaults to |
- | | | 0. |
- +------------------------------------------------------------------------+
+ $VIEW() provides a means to access GT.M environmental information. When
+ GT.M permits modification of the factors accessible with $VIEW(), the VIEW
+ command generally provides the means for effecting the change.
+
+ +----------------------------------------------------------------------------------------------------------------------------------------------------+
+ | $VIEW() Argument Keywords |
+ |----------------------------------------------------------------------------------------------------------------------------------------------------|
+ | ARG 1 | ARG 2 | RETURN VALUE |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"BADCHAR" |none |In UTF-8 mode processes, enables or disable the generation of an error when character-oriented functions encounter |
+ | | |malformed byte sequences (illegal characters). The default is 1. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"BREAKMSG" |none |Value of the break message mask; GT.M defaults this to 31. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"FREEBLOCKS" |region |Number of free database blocks in a given region. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Process-id of a process that has frozen the database associated with the region specified (using DSE or MUPIP). |
+ |"FREEZE" |region | |
+ | | |If the region is currently not frozen, returns zero. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Returns a string describing the current compiler setting. The default is "GT.M Boolean short-circuit". |
+ |"FULL_BOOLEAN" |none |$VIEW("FULL_BOOLEAN") reports "Standard Boolean evaluation side effects" when it is not explicitly set, but that |
+ | | |mode of operation is required by the setting of gtm_side_effects, and "Standard Boolean side-effect warning" when |
+ | | |warnings have been specified. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Truth Value indicating whether Database block certification is currently enabled or disabled. |
+ |"GDSCERT" |none | |
+ | | |To enable or disable Database block certification, use the VIEW "GDSCERT" command. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"GVACCESS_METHOD"|region |Access method of the region. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"GVFILE" |region |Name of the database associated with the region. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"GVFIRST" |none |Name of the first database region in the current global directory; functionally equivalent to $VIEW("GVNEXT",""). |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"GVNEXT" |region |Name of the next database region after the given one in alphabetical order (or M collation sequence); "" for region|
+ | | |starts with the first region. A return value of "" means that the global directory defines no additional regions. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Encoded information about database behavior since segment creation. It also includes SET operations even if they |
+ | | |are inside a TP transaction. |
+ | | | |
+ |"GVSTAT" |region |If you require completely accurate GVSTATS, you need to ensure the last process to close a database always has |
+ | | |write access to the database files. If read-only processes are the active processes in a database, they cannot |
+ | | |update the database and may delete the shared memory where they have stored the counts of their actions (for |
+ | | |example, the number of blocks read). |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Number of indirection cache hits since GT.M process startup. |
+ |"ICHITS" |none | |
+ | | |Indirection cache is a pool of compiled expressions that GT.M maintains for indirection and XECUTE. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"ICMISS" |none |Number of indirection cache misses since GT.M process startup. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |can return the following values: |
+ | | | |
+ |"JNLACTIVE" |region | * -1 (internal error) |
+ | | | * 0 journaling is disabled |
+ | | | * 1 journaling is enabled but closed (OFF) |
+ | | | * 2 journaling is enabled and open (ON) |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"JNLFILE" |region |Journal file name associated with the region. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"JNLTRANSACTION" |none |Index showing how many ZTSTART transaction fences have been opened (and not closed). |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"LABELS" |none |Truth value showing whether label case sensitivity is ON (1 for "LOWER") or OFF (0 for "UPPER"); GT.M defaults to |
+ | | |1. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"LINK" |none |Returns the current relink recursive setting of ZLINK. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | |local variable|returns the number of references by alias containers to the array associated with an unsubscripted local variable |
+ |"LV_CREF" |name (lvn) |name specified as a second expr (for example a quoted string); it returns a zero for a variable without any |
+ | | |associated alias container. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"LV_GCOL" |none |returns the number of data-spaces recovered during a local variable data-space garbage collection it triggers; such|
+ | | |collections normally happen automatically at appropriate times. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"LV_REF" |local variable|returns the total number of references to the data-space associated with an unsubscripted local variable name |
+ | |name (lvn) |specified as a second expr (for example a quoted string). |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"LVNULLSUBS" |none |Truth value showing whether null subscripts are permitted in local arrays (1 for "LVNULLSUBS") or not (0 for |
+ | | |"NOLVNULLSUBS"); GT.M defaults to 1. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |The current isolation-status of the specified global variable which must have a leading "^" in its specification. |
+ | | | |
+ | | |This function returns 1 if GT.M has been instructed to not enforce the ACID property of Isolation (that is, |
+ |"NOISOLATION" |global |"NOISOLATION" has been specified) and 0 otherwise. |
+ | | | |
+ | | |By default, GT.M ensures Isolation, that is, a $VIEW command will return 0. The isolation-status of a global |
+ | | |variable can be turned on and off by the VIEW "NOISOLATION" command. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Name of the region(s) holding the specified gvn. |
+ | | | |
+ | | |If gvn spans more than one region, this function returns region name in an order where the first region is the |
+ | | |region to which the unsubscripted global variable name maps; and other regions are in the order in which they would|
+ |"REGION" |gvn |be encountered by traversing the subscripts of gvn in order (with duplicates removed). |
+ | | | |
+ | | |gvn is a subscripted or unsubscripted global variable name in the same form as that generated by $NAME(). You can |
+ | | |use $NAME() inside $VIEW() to ensure that subscripts are in a correct form, for example, |
+ | | |$VIEW("REGION",$NAME(^abcd(1,2E4))) instead of $VIEW("REGION","^abcd(1,20000)"). |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"PATCODE" |none |Name of the active patcode table; GT.M defaults this to "M". |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"RTNCHECKSUM" |routine name |Returns the source check-sum for the most recently ZLINK'd version of the specified routine name. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"RTNNEXT" |routine name |Name of the next routine in the image after the given one; "" (empty string) for routinename starts with the first |
+ | | |routine in ASCII collating sequence and a return value of the empty string indicates the end of the list. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Number of bytes in the currently allocated as process working storage. GT.M manages this space as what is commonly |
+ |"SPSIZE" |none |called a heap, and uses the term stringpool to refer to it. The GT.M garbage collector reclaims unused space from |
+ | | |the stringpool from time to time, and GT.M automatically expands the stringpool as needed by the application |
+ | | |program. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"STKSIZ" |none |Returns the GT.M stack size in bytes. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"TOTALBLOCKS" |region |Total number of database blocks in a given region. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | |NULL |Transaction ID specified in the particular level (when the transaction level is specified). The first level TSTART |
+ | | |is returned if the level is not specified as second argument. |
+ | |or | |
+ |"TRANSACTIONID" | | **Note** |
+ | |transaction | |
+ | |level |A NULL string is returned if the specified level (explicitly or implicitly) is greater than the current value of |
+ | | |$TLEVEL. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"UNDEF" |none |Truth value showing whether undefined variables should be treated as having a null value (1 for "UNDEF"; 0 for |
+ | | |"NOUNDEF"); GT.M defaults to 0. |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Displays the database representation of gvn where gvn is a global name or a global name with subscript(s). The |
+ | | |option collnum specifies the alternate collation sequence number. If collnum is not specified, GT.M assumes the |
+ | | |default ASCII collation(collnum=0). For example: |
+ |"YGVN2GDS" |gvn[,collnum])| |
+ | | |GTM>set x=$VIEW("YGVN2GDS","^A(1,""abcd"")") zwrite x for i=1:1:$zlength(x) write $zascii($zextract(x,i))," " |
+ | | |x="A"_$C(0)_" "_$C(17,0,255)_"abcd"_$C(0,0) |
+ | | |65 0 191 17 0 255 97 98 99 100 0 0 |
+ | | |GTM> |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ | | |Displays the global name or a global name with subscript(s) of a database representation gds. The option collnum |
+ | | |specifies the collnum specifies the alternate collation sequence number. If collnum is not specified, GT.M assumes |
+ | | |the default ASCII collation(collnum=0). This function is the inverse of the $VIEW("YGVN2GDS",<gvn>[,collnum]) |
+ | | |function. For example: |
+ |"YGDS2GVN" |gds[,collnum])| |
+ | | |GTM>set y=$VIEW("YGDS2GVN",x) zwrite y |
+ | | |y="^A(1,""abcd"")" |
+ | | | |
+ | | |GTM> |
+ |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------|
+ |"ZDATE_FORM" |none |Integer value showing whether four digit year code is active for $ZDATE(); GT.M defaults to 0 (for "YY" format). |
+ | | |Use the environment variable gtm_zdate_form to set the initial value of this factor. |
+ +----------------------------------------------------------------------------------------------------------------------------------------------------+
**Important**
@@ -8705,17 +8581,6 @@
Example:
- set len=$length(name)
- set be4=$extract(name,1,len-1)_$char($ascii(name,len)-1)
- i $view("RTNNEXT",be4_$extract("ZZZZZZZ",1,8-len))=name do
- . zlink name
-
- Given a routine name this uses $VIEW() to determine whether the location
- contains the routine. If the routine already exists the ZLINK replaces it.
- Otherwise, auto-ZLINK will bring in a new copy.
-
- Example:
-
GTM>Set a=1,*b(1)=a
GTM>write $view("LV_CREF","a")," ",$view("LV_CREF","b")
@@ -8751,6 +8616,41 @@
2,TBR:80,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:7
GTM>
+ These are statistics associated with the DEFAULT region. Refer to
+ "ZSHOW Information Codes" for information on the parameters.
+
+ Example:
+
+ Given the following global directory configuration:
+
+ GDE>add -name a(1:10) -region=a1
+ GDE>add -name a(10,1) -region=a2
+ GDE>add -name a(10,2) -region=a3
+ GDE>add -name a(120:300) -region=a4
+ GDE>add -name a(60:325) -region=a5
+ GDE> show -name
+ *** NAMES ***
+ Global Region
+ ------------------------------------------------------------------------------
+ * DEFAULT
+ a(1:10) A1
+ a(10,1) A2
+ a(10,2) A3
+ a(60:120) A5
+ a(120:300) A4
+ a(300:325) A5
+
+ Here are some $VIEW("REGION",gvn) outputs:
+
+ GTM>write $view("REGION","^a(1)")
+ A1
+ GTM>write $view("REGION","^a(10)")
+ DEFAULT,A2,A3
+ GTM>w $view("REGION","^a(60)")
+ A5
+ GTM>w $view("REGION","^a")
+ DEFAULT,A1,A2,A3,A5,A4
+
2 $ZAHandle()
$ZAHandle()
@@ -9685,7 +9585,7 @@
GTM>set x="*"_$zchar(63)_"*"_$zchar(63)_"*"
GTM>write $zlength(x,$zchar(63))
- 2
+ 3
GTM>
This uses $ZLENGTH() to WRITE the number of pieces in a sequence of
@@ -9694,14 +9594,14 @@
Example:
GTM>set x=$zchar(63)_"*"_$zchar(63)_"*"_$zchar(63)_"*"_$zchar(63)"
- GTM>write $zlength(x,$zchar(63)
- 4
+ GTM>write $zlength(x,$zchar(63))
+ 5
GTM>
This also uses $ZLENGTH() to WRITE the number of pieces in a sequence of
- octets, as delimited by byte code $ZCHAR(63). Notice that GT.M. counts
- both the empty beginning and ending pieces , in the string because they
- are both delimited.
+ octets, as delimited by byte code $ZCHAR(63). Notice that GT.M counts both
+ the empty beginning and ending pieces in the string because they are both
+ delimited.
2 $ZMessage()
$ZMessage()
@@ -9911,6 +9811,119 @@
$ZCHAR(64). This produces a byte sequence of 24 at-signs (@) preceding the
null.
+2 $ZPEEK()
+ $ZPEEK()
+
+ Provides a way to examine memory in the current process address space. It
+ is intended as a tool to make it more convenient for FIS to access
+ information in the address space of processes more efficiently than by
+ calling out to external functions. It is documented here for completeness.
+ While FIS normally maintains stability of GT.M functionality from release
+ to release, this function is not designed for non-FIS usage, and FIS may
+ change or eliminate this function at any time.
+
+ The $ZPEEK() function returns the contents of the memory requested as a
+ string depending on the requested (or defaulted) formatting.
+
+ The format of the $ZPEEK() function is:
+
+ $ZPEEK("mnemonic[:argument]",offset,length[,format])
+
+ o mnemonic specifies the memory area $ZPEEK() is to access. Some
+ mnemonics have arguments separated from the mnemonic by a colon (":").
+ The mnemonics are case independent. Possible mnemonics, their possible
+ abbreviations and their arguments are:
+
+ o CSA[REG] - returns a value from the sgmnt_addrs (process private)
+ control block. Takes a case independent region name as an
+ argument.
+ o FH[REG] - returns a value from the sgmnt_data (shared file
+ header) control block. Takes a case independent region name as an
+ argument.
+ o GDR[REG] - returns a value from the gd_region (process private)
+ control block. Takes a case independent region name as an
+ argument.
+ o GLF[REPL] - returns a value from the jnlpool.gtmsrc_lcl_array[n]
+ control block. Takes a numeric index (n) as an argument.
+ o GRL[REPL] - returns a value from the recvpool.gtmrecv_local
+ control block. No argument allowed. Only available when run on a
+ non-primary instance.
+ o GSL[REPL] - returns a value from the
+ jnlpool.gtmsource_local_array[n] control block. Takes a numeric
+ index (n) as an argument.
+ o JPC[REPL] - returns a value from the jnlpool.jnlpool_ctl control
+ block. No argument allowed.
+ o NL[REG] - returns a value from the node_local (shared) control
+ block. Takes a case independent region name as an argument.
+ o NLREPL - returns a value from the node_local (shared) control
+ block associated with replication. No argument allowed.
+ o PEEK - returns a value based on the supplied argument. Argument
+ is the base address of whatever is being fetched in 0xhhhhhhh
+ format where the h's are hex digits.
+ o RIH[REPL] - returns a value from the jnlpool.repl_inst_filehdr
+ control block. No argument allowed.
+ o RPC[REPL] - returns a value from the recvpool.recvpool_ctl
+ control block. No argument allowed. Only available when run on a
+ non-primary instance.
+ o UHC[REPL] - returns a value from the recvpool.upd_helper_ctl
+ control block. No argument allowed. Only available when run on a
+ non-primary instance.
+ o UPL[REPL] - returns a value from the recvpool.upd_proc_local
+ control block. No argument allowed. Only available when run on a
+ non-primary instance.
+
+ o offset (first integer expression) is a numeric value that specifies
+ the offset from the address supplied or implied by the the mnemonic
+ and argument. Specifying a negative offset results in a BADZPEEKARG
+ error. Specifying too large an offset such that unavailable memory is
+ specified results in a BADZPEEKRANGE error.
+ o length (second integer expression) is a numeric value that specifies
+ the length of the field to be fetched. Specifying a negative legnth
+ results in a BADZPEEKARG error. Specifying a length that exceeds the
+ maximum string length results in a MAXSTRLEN error. Specifying too
+ large a length such that unavailable memory is specified results in a
+ BADZPEEKRANGE error.
+ o format is an optional single case independent character formatting
+ code for the retrieved data. The formatting codes are:
+
+ o C : returns a character representations of the memory locations;
+ this is the DEFAULT if the fourth argument is not specified.
+ o I : returns a signed integer value - negative values have a
+ preceding minus sign (-); the length can be 1, 2, 4, or 8 bytes.
+ o U : returns an unsigned integer value - all bits are part of the
+ numeric value; the length can be 1, 2, 4, or 8 bytes.
+ o S : returns a character representation of the memory locations
+ and the first NULL character found terminates the returned
+ string; that is: the specified length is a maximum.
+ o X : returns a hexadecimal value as 0xXXXXXX where XXXXXX is twice
+ the specified length in bytes, so requested length 1 returns 0xXX
+ and length 4 returns 0xXXXXXXXX; the length can be 1, 2, 4, or 8
+ bytes.
+ o Z : returns a hexadecimal representation of the memory locations
+ as 'X' does, without regard to endianness, and with no length
+ restriction other than max string length.
+ o $ZPEEK() function generates an UNDEF error when VIEW UNDEF is not
+ set and format parameter is specified but is undefined.
+
+ **Note**s
+
+ o $ZPEEK() has no UTF-8 checking. It is possible for values returned by
+ the 'C' and 'S' codes to have invalid UTF-8 values in them. Take care
+ when processing values obtained by these codes to either use "VIEW
+ NOBADCHAR" when dealing with such values and/or use the $Zxxx()
+ flavors of functions like $ZPIECE(), $ZEXTRACT(),etc which also do not
+ raise BADCHAR errors when encountering invalid UTF-8 encoded strings.
+ o Note that $ZPEEK() with 8 byte numeric formatting can return numeric
+ string values that exceed GT.M's current limit of 18 digits of
+ precision. If the values are used as strings, the extra digits are
+ preserved, but if used arithmetically, the lower precision digits can
+ be lost.
+ o When values from replication structures are requested and the
+ structures are not available due to replication not running or, in the
+ case of the gtmrecv.* control block base options, if not running on a
+ non-primary instance where the gtmrecv.* control are available, a
+ ZPEEKNOREPLINFO error is raised.
+
2 $ZPrevious()
$ZPrevious()
@@ -9932,6 +9945,117 @@
$ZPREVIOUS() is equivalent to $ORDER() with a second argument of -1.
+2 $ZSOCKET()
+ $ZSOCKET()
+
+ Returns information about a SOCKET device and its attached sockets. The
+ format of the $ZSOCKET() function is:
+
+ $ZSOCKET(expr1,expr2[,[expr3][,expr4]])
+
+ o The first expression specifies the SOCKET device name; an empty string
+ returns the same result as the current device ($IO). If the first
+ expression is not specified, $ZSOCKET() returns information about
+ sockets in the socketpool. Specifying a device other than a SOCKET
+ device for the $ZSOCKET() function produces a ZSOCKETNOTSOCK error.
+ o The second expression specifies a keyword identifying the type of
+ information returned and the optional third expression usually
+ specifies the index (starting at zero) of a socket attached to the
+ device; if the index is outside the range of attached sockets,
+ $ZSOCKET() returns an empty string. If the third expression is not
+ specified, $ZSOCKET() returns information about the current socket.
+ Using an invalid keyword produces a ZSOCKETATTR error. The fourth
+ expression specifies an individual delimiter when the second
+ expression specifies DELIMITER. For more information, see the
+ following table. Note that changes to the socket collection for a
+ SOCKET device using OPEN, CLOSE, USE :ATTACH, or USE :DETACH may
+ change the index for a socket.
+
+ +------------------------------------------------------------------------+
+ | Keyword | Arguments | Returns |
+ |---------------+------------+-------------------------------------------|
+ | CURRENTINDEX | | The index (starting at zero) of the |
+ | | | current socket for the SOCKET device. |
+ |---------------+------------+-------------------------------------------|
+ | | | If only index is specified, the number of |
+ | | | delimiters. |
+ | DELIMITER | index[, | |
+ | | delimiter] | If delimiter is also specified, selects |
+ | | | which delimiter to return. The first |
+ | | | delimiter is zero. |
+ |---------------+------------+-------------------------------------------|
+ | DESCRIPTOR | index | The OS socket descriptor for the socket. |
+ |---------------+------------+-------------------------------------------|
+ | | | LISTEN, CONNECT, ACCEPTED, PRINCIPAL, or |
+ | | | PASSED |
+ | | | |
+ | HOWCREATED | index | PRINCIPAL indicates that the socket is |
+ | | | the $PRINCIPAL of the process. |
+ | | | |
+ | | | PASSED indicates a socket passed by WRITE |
+ | | | /ACCEPT. |
+ |---------------+------------+-------------------------------------------|
+ | INDEX | handle | The current index of the socket named by |
+ | | | handle. |
+ |---------------+------------+-------------------------------------------|
+ | IOERROR | index | 1 if IOERROR=TRAP otherwise 0. |
+ |---------------+------------+-------------------------------------------|
+ | | | The address of the local side of the |
+ | LOCALADDRESS | index | socket. For TCP sockets: the IPv4 or IPv6 |
+ | | | numeric address. For LOCAL socket: the |
+ | | | path. |
+ |---------------+------------+-------------------------------------------|
+ | LOCALPORT | index | The numeric port of the local side of a |
+ | | | TCP socket. |
+ |---------------+------------+-------------------------------------------|
+ | | | The value of the MOREREADTIME device |
+ | MOREREADTIME | index | parameter if it was specified, otherwise |
+ | | | an empty string. |
+ |---------------+------------+-------------------------------------------|
+ | NUMBER | | The number of sockets in the SOCKET |
+ | | | device. |
+ |---------------+------------+-------------------------------------------|
+ | | | If the socket was created from a |
+ | PARENT | index | LISTENing socket: the handle of the |
+ | | | LISTENing socket. |
+ |---------------+------------+-------------------------------------------|
+ | PROTOCOL | index | TCP, TCP6, or LOCAL |
+ |---------------+------------+-------------------------------------------|
+ | | | The address of the remote side of the |
+ | REMOTEADDRESS | index | socket. For TCP sockets: the IPv4 or IPv6 |
+ | | | numeric address. For LOCAL socket: the |
+ | | | path. |
+ |---------------+------------+-------------------------------------------|
+ | REMOTEPORT | index | The numeric port of the remote side of a |
+ | | | TCP socket. |
+ |---------------+------------+-------------------------------------------|
+ | SOCKETHANDLE | index | The handle for the selected socket. |
+ |---------------+------------+-------------------------------------------|
+ | STATE | index | One of LISTENING, CONNECTED, BOUND, or |
+ | | | CONNECTINPROGRESS |
+ |---------------+------------+-------------------------------------------|
+ | ZBFSIZE | index | Size of the GT.M buffer in bytes. |
+ |---------------+------------+-------------------------------------------|
+ | ZFF | index | The value of the ZFF device parameter. |
+ |---------------+------------+-------------------------------------------|
+ | ZIBFSIZE | index | Size of the OS buffer in bytes |
+ | | | (SO_RCVBUF). |
+ |---------------+------------+-------------------------------------------|
+ | ZDELAY | index | 1 if Nagle algorithm enabled, otherwise |
+ | | | 0. |
+ +------------------------------------------------------------------------+
+
+2 $ZSYSLOG()
+ $ZSYSLOG()
+
+ Sends its string parameter to the system log and always returns TRUE (1).
+ The text appears in the syslog with the same format as any other GT.M
+ syslog message (that is, in the user.info log with GTM-MUMPS[pid]" or
+ "GTM-MUPIP[pid]" prefix along with instance information where
+ appropriate). The format of the $ZSYSLOG function is:
+
+ $ZSYSLOG(expr)
+
2 $ZQGBLMOD()
$ZQGBLMOD()
@@ -10168,6 +10292,8 @@
3 Examples_of_$ZTRIGGER()
Examples of $ZTRIGGER()
+ Example:
+
GTM>set X=$ztrigger("S")
GTM>
@@ -10179,6 +10305,35 @@
This example adds a trigger definition for the first level node of ^Acct.
+ Example:
+
+ GTM>set trigstr="+^a -commands=S -xecute=<<"_$c(10)_" do ^twork1"_$c(10)_" do ^twork2"_$c(10) write $ztrigger("item",trigstr)
+
+ This example demonstrates the usage of the
+ $ztrigger("ITEM",<multi-line-trigger-definition>> where <<denotes the
+ definition of a multi-line -XECUTE string and $c(10) to denote the newline
+ separator. Unlike the $ztrigger("FILE") form,
+ $ztrigger("ITEM",<multi-line-trigger-definition>> does not require trigger
+ definition to terminate with >>.
+
+ Example:
+
+ GTM>write $ztrigger("file","agbl.trg")
+ 1
+ GTM>
+
+ This example is equivalent to the previous $ztrigger("ITEM") example. In
+ this example, agbl.trg contains the following multi-line trigger
+ definition:
+
+ +^a -commands=S -xecute=<<
+ do ^twork1
+ do ^twork2
+ >>
+
+ Unlike $ztrigger("ITEM"), $ztrigger("FILE") usages require the trigger
+ definition to terminate with >>
+
2 $ZTRNLNM()
$ZTRNLNM()
@@ -10403,6 +10558,13 @@
$ETRAP with the SET command initiates a new trap; it does not save the old
trap.
+ $ETRAP may also appear as an argument to an inclusive NEW command. NEW
+ $ETRAP causes GT.M to stack the active condition handler's ($ETRAP or
+ $ZTRAP) old value. If $ZTRAP is the active condition handler, the NEW
+ implicitly sets the current $ZTRAP value to null. NEW leaves the $ETRAP
+ unchanged regardless of the previously active condition handler. The NEW
+ command puts the target ISV in control for error handling.
+
For more examples of the use of special variable $ETRAP, see the function
$STACK().
@@ -10456,17 +10618,55 @@
$K[EY] contains the string that terminated the most recent READ command
from the current device (including any introducing and terminating
- characters). If no READ command s issued to the current device or if no
+ characters). If no READ command was issued to the current device or if no
terminator is used, the value of $KEY is an empty string. However, when
input is terminated by typing a function key, the value of $KEY is equal
to the string of characters that is transmitted by that function key.
The effect of a READ *glvn on $KEY is unspecified.
- If a Character Set Profile input-transform is in effect, then this is also
- applied to the value stored in $KEY.
+ For terminals, $KEY and $ZB both have the terminator.
+
+ For SOCKET:
+
+ $KEY contains the socket handle and the state information of the current
+ SOCKET device after certain I/O commands.
- For terminals, $ZB has the terminator.
+ After a successful OPEN or USE with the LISTEN deviceparameter, $KEY
+ contains for TCP sockets:
+
+ "LISTENING|<socket_handle>|<portnumber>"
+
+ and for LOCAL sockets:
+
+ "LISTENING|<socket_handle>|<address>"
+
+ After a successful OPEN or USE with the CONNECT device parameter or when
+ GT.M was started with a socket as the $PRINCIPAL device, $KEY contains:
+
+ "ESTABLISHED|<socket handle>|<address>"
+
+ When WRITE /WAIT selects an incoming connection, $KEY contains:
+
+ "CONNECT|<socket_handle>|<address>"
+
+ When WRITE /WAIT selects a socket with data available for reading, $KEY
+ contains:
+
+ "READ|<socket_handle>|<address>"
+
+ For TCP sockets, <address> is the numeric IP address for the remote end of
+ the connection. For LOCAL sockets it is the path to the socket.
+
+ For TCP LISTENING sockets, <portnumber> is the local port on which
+ socket_handle is listening for incoming connections. For LOCAL LISTENING
+ sockets, it is the path of the socket.
+
+ If the WRITE /WAIT was timed, $KEY returns an empty value if the wait
+ timed out or there was no established connection. $KEY only has the
+ selected handle, if any, immediately after a WRITE /WAIT. $KEY is also
+ used by other socket I/O commands such as READ which sets it to the
+ delimiter or bad Unicode character, if any, which terminated the read.
2 $Principal
$Principal
@@ -10496,6 +10696,20 @@
GT.M ignores a CLOSE specifying the principal device. GT.M does not permit
the SET command to modify $PRINCIPAL.
+ GT.M discards reads and writes against an empty socket device (that is,
+ one with all sockets detached) if it is the $PRINCIPAL device.
+
+ GT.M opens /dev/null as a placeholder for a socket which used to be
+ associated with $PRINCIPAL via stdin when it is closed.
+
+ GT.M creates a SOCKET device for $PRINCIPAL when standard input is a LOCAL
+ domain socket and sets the default DELIMITER to "$C(10)" for sockets in
+ the device.
+
+ When $PRINCIPAL identifies a device that supports REWIND, the REWIND or
+ INREWIND device parameters perform a REWIND of the input and OUTREWIND
+ performs a REWIND of the output.
+
2 $Quit
$Quit
@@ -10613,6 +10827,8 @@
process wide basis. Use $TEST only in immediate proximity to the operation
that last updated it.
+ Neither $SELECT() nor post-conditional expressions modify $TEST.
+
M routines cannot modify $TEST with the SET command.
Example:
@@ -10911,3181 +11127,5622 @@
When $ZCOMPILE is null, GT.M uses the default M command qualifiers
-IGNORE, -LABEL=LOWER, -NOLIST, and -OBJECT.
- Example:
+ Example:
+
+ $ export gtmcompile="-LIST -LENGTH=56 -SPACE=2"
+ $ gtm
+ GTM>WRITE $ZCOMPILE
+ -LIST -LENGTH=56 -SPACE=2
+ GTM>SET $ZCOMPILE="-LIST -NOIGNORE"
+ GTM>WRITE $ZCOMPILE
+ -LIST -NOIGNORE
+ GTM>ZLINK "A.m"
+ GTM>HALT
+ $ echo $gtmcompile
+ -LIST -LENGTH=56 -SPACE=2
+
+ This example uses the environment variable gtmcompile to set up $ZCOMPILE.
+ Then it modifies $ZCOMPILE with the SET command. The ZLINK argument
+ specifies a file with a .m extension (type), which forces a compile. The
+ compile produces a listing for routine A.m and does not produce an object
+ module if A.m contains compilation errors. After GT.M terminates, the
+ shell command echo $gtmcompile demonstrates that the SET command did not
+ change the environment variable.
+
+2 $ZCstatus
+ $ZCstatus
+
+ $ZC[STATUS] holds the value of the status code for the last compilation
+ performed by a ZCOMPILE command.
+
+ GT.M does not permit the SET command to modify $ZSTATUS.
+
+2 $ZCLose
+ $ZCLose
+
+ Provides termination status of the last PIPE CLOSE as follows:
+
+ o -99 when the check times out
+ o -98 for unanticipated problems with the check
+ o the negative of the signal value if a signal terminated the
+ co-process.
+
+ If positive, $ZCLOSE contains the exit status returned by the last
+ co-process.
+
+2 $ZDAteform
+ $ZDAteform
+
+ $ZDA[TEFORM] contains an integer value, specifying the output year format
+ of $ZDATE(). $ZDATEFORM can be modified using the SET command. GT.M
+ initializes $ZDATEFORM to the translation of the environment variable
+ gtm_zdate_form. If gtm_zdate_form is not defined, GT.M initializes
+ $ZDATEFORM to zero (0).
+
+ Refer to "Functions" and "Utility Routines" chapters in the GT.M
+ Programmer's Guide for more details.
+
+ Example:
+
+ GTM>WRITE $ZDATEFROM
+ 0
+ GTM>WRITE $ZDATE($H)
+ 11/15/02
+ GTM>SET $ZDATEFORM=1
+ GTM>WRITE $ZDATE($H)
+ 11/15/2002
+
+2 $ZDirectory
+ $ZDirectory
+
+ $ZD[IRECTORY] contains the string value of the full path of the current
+ directory. Initially $ZDIRECTORY contains the default/current directory
+ from which the GT.M image/process was activated.
+
+ If the current directory does not exist at the time of GT.M process
+ activation, GT.M errors out.
+
+ Example:
+
+ GTM>WRITE $ZDIR
+ /usr/tmp
+ GTM>SET $ZDIR=".."
+ GTM>WRITE $ZDIR
+ /usr
+
+ This example displays the current working directory and changes $ZDIR to
+ the parent directory.
+
+ $ZDIRECTORY is a read-write Intrinsic Special Variable, that is, it can
+ appear on the left side of the equal sign (=) in the argument to a SET
+ command. If an attempt is made to set $ZDIRECTORY to a non-existent
+ directory specification, GT.M issues an error and keeps the value of
+ $ZDIRECTORY unchanged.
+
+ At image exit, GT.M restores the current directory to the directory that
+ was the current directory when GT.M was invoked even if that directory
+ does not exist.
+
+2 $ZEDit
+ $ZEDit
+
+ $ZED[IT] holds the value of the status code for the last edit session
+ invoked by a ZEDIT command.
+
+ GT.M does not permit the SET or NEW command to modify $ZEDIT.
+
+2 $ZEOf
+ $ZEOf
+
+ $ZEO[F] contains a truth-valued expression indicating whether the last
+ READ operation reached the end-of-file. $ZEOF equals TRUE (1) at EOF and
+ FALSE (0) at other positions.
+
+ GT.M does not maintain $ZEOF for terminal devices.
+
+ $ZEOF refers to the end-of-file status of the current device. Therefore,
+ exercise care in sequencing USE commands and references to $ZEOF.
+
+ GT.M does not permit the SET or NEW command to modify $ZEOF.
+
+ For more information on $ZEOF, refer to the "Input/Output Processing"
+ chapter.
+
+2 $ZError
+ $ZError
+
+ $ZE[RROR] is supposed to hold the application-specific error-code
+ corresponding to the GT.M error-code stored in $ECODE/$ZSTATUS.
+
+ $ZERROR contains a default value of "Unprocessed $ZERROR, see $ZSTATUS" at
+ process startup.
+
+ $ZERROR can be SET but not NEWed.
+
+ The mapping of a GT.M error-code to the application-specific error-code is
+ achieved as follows. Whenever GT.M encounters an error, $ECODE/$ZSTATUS
+ gets set first. It then invokes the code that $ZYERROR points to if it is
+ not null. It is intended that the code invoked by $ZYERROR use the value
+ of $ZSTATUS to select or construct a value to which it SETs $ZERROR. If an
+ error is encountered by the attempt to execute the code specified in
+ $ZYERROR, GT.M sets $ZERROR to the error status encountered. If $ZYERROR
+ is null, GT.M does not change the value of $ZERROR. In all cases, GT.M
+ proceeds to return control to the code specified by $ZTRAP/$ETRAP or
+ device EXCEPTION whichever is applicable.
+
+2 $ZGbldir
+ $ZGbldir
+
+ $ZG[BLDIR] contains the value of the current Global Directory filename.
+ When $ZGBLDIR specifies an invalid or inaccessible file, GT.M cannot
+ successfully perform database operations.
+
+ GT.M initializes $ZGBLDIR to the translation of the environment variable
+ gtmgbldir. The value of the gtmgbldir environment variable may include a
+ reference to another environment variable. If gtmgbldir is not defined,
+ GT.M initializes $ZGBLDIR to null. When $ZGBLDIR is null, GT.M constructs
+ a file name for the Global Directory using the name $gtmgbldir and the
+ extension .gld in the current working directory.
+
+ $ZGBLDIR is a read-write Intrinsic Special Variable, (i.e., it can appear
+ on the left side of the equal sign (=) in the argument to the SET
+ command). SET $ZGBLDIR="" causes GT.M to assign $ZGBLDIR to the
+ translation of gtmgbldir if that environment variable is defined. If it is
+ not defined, then SET $ZGBLDIR="" causes GT.M to construct a file name
+ using the name $gtmgbldir.gld in the current directory. GT.M permits
+ $ZGBLDIR to be NEW'd. A $ZGBLDIR value may include an environment
+ variable.
+
+ SETting $ZGBLDIR also causes GT.M to attempt to open the specified file.
+ If the file name is invalid or the file is inaccessible, GT.M triggers an
+ error without changing the value of $ZGBLDIR.
+
+ To establish a value for $ZGBLDIR outside of M, use the appropriate shell
+ command to assign a translation to gtmgbldir. Defining gtmgbldir provides
+ a convenient way to use the same Global Directory during a session where
+ you repeatedly invoke and leave GT.M.
+
+ Changes to the value of $ZGBLDIR during a GT.M invocation only last for
+ the current invocation and do not change the value of gtmgbldir.
+
+ Example:
+
+ $ gtmgbldir=test.gld
+ $ export gtmgbldir
+ $ gtm
+ GTM>WRITE $zgbldir
+ /usr/dev/test.gld
+ GTM>SET $zgbldir="mumps.gld"
+ GTM>WRITE $zgbldir
+ mumps.gld
+ GTM>HALT
+ $ echo $gtmgbldir
+ test.gld
+
+ This example defines the environment variable gtmgbldir. Upon entering
+ GT.M Direct Mode, $ZGBLDIR has the value supplied by gtmgbldir. The SET
+ command changes the value. After the GT.M image terminates, the echo
+ command demonstrates that gtmgbldir was not modified by the M SET command.
+
+ $ ls test.gld
+ test.gld not found
+ $ gtm
+ GTM>WRITE $zgbldir
+ /usr/dev/mumps.gld
+ GTM>set $zgbldir="test.gld"
+ %GTM-E-ZGBLDIRACC, Cannot access global directory
+ "/usr/dev/test.gld". Retaining /usr/dev/mumps.gld"
+ %SYSTEM-E-ENO2, No such file or directory
+ GTM>WRITE $zgbldir
+ /usr/dev/mumps.gld
+ GTM>halt
+ $
+
+ The SET command attempts to change the value of $ZGBLDIR to test.gld.
+ Because the file does not exist, GT.M reports an error and does not change
+ the value of $ZGBLDIR.
+
+ **Caution**
+
+ Attempting to restore an inaccessible initial Global Directory that has
+ been NEW'd, can cause an error.
+
+ Note
+
+ Attempting to restore an inaccessible initial Global Directory that has
+ been NEW'd, can cause an error.
+
+2 $ZINTerrupt
+ $ZINTerrupt
+
+ $ZINT[ERRUPT] specifies the code to be XECUTE'd when an interrupt (for
+ example, through a MUPIP INTRPT) is processed. While a $ZINTERRUPT action
+ is in process, any additional interrupt signals are discarded. When an
+ interrupt handler is invoked, the current values of $REFERENCE is saved
+ and restored when the interrupt handler returns. The current device ($IO)
+ is neither saved nor restored.
+
+ GT.M permits the SET command to modify the value of $ZINTERRUPT.
+
+ If an interrupt handler changes the current IO device (via USE), it is the
+ responsibility of the interrupt handler to restore the current IO device
+ before returning. There are sufficient legitimate possibilities why an
+ interrupt routine would want to change the current IO device (for example;
+ daily log switching), that this part of the process context is not saved
+ and restored automatically.
+
+ The initial value for $ZINTERRUPT is taken from the UNIX environment
+ variable gtm_zinterrupt if it is specified, otherwise it defaults to the
+ following string:
+
+ IF $ZJOBEXAM()
+
+ The IF statement executes the $ZJOBEXAM function but effectively discards
+ the return value.
+
+ **Note**
+
+ If the default value for $ZINTERRUPT is modified, no $ZJOBEXAM() will
+ occur unless the replacement value directly or indirectly invokes that
+ function. In other words, while $ZJOBEXAM() is part of the interrupt
+ handling by default, it is not an implicit part of the interrupt handling.
+
+3 Interrupt_Handling
+ Interrupt Handling
+
+ GT.M process execution is interruptible with the following events:
+
+ When GT.M detects any of these events, it transfers control to a vector
+ that depends on the event. For CTRAP characters and ZMAXTPTIME, GT.M uses
+ the $ETRAP or $ZTRAP vectors described in more detail in the Error
+ Processing chapter. For INTRPT and $ZTEXit, it XECUTEs the interrupt
+ handler code placed in $ZINTERRUPT. If $ZINTERRUPT is an empty string,
+ nothing is done in response to a MUPIP INTRPT. The default value of
+ $ZINTERRUPT is "IF $ZJOBEXAM()" which redirects a dump of ZSHOW "*" to a
+ file and reports each such occasion to the operator log. For CTRL+C with
+ CENABLE, it enters Direct Mode to give the programmer control.
+
+ GT.M recognizes most of these events when they occur but transfers control
+ to the interrupt vector at the start of each M line, at each iteration of
+ a FOR LOOP, at certain points during the execution of commands which may
+ take a "long" time. For example, ZWRITE, HANG, LOCK, MERGE, ZSHOW "V",
+ OPENs of disk files and FIFOs, OPENs of SOCKETs with the CONNECT parameter
+ (unless zero timeout,) WRITE /WAIT for SOCKETs, and READ for terminals,
+ SOCKETs, FIFOs, and PIPEs. If +$ZTEXIT evaluates to a truth value at the
+ outermost TCOMMIT or TROLLBACK, GT.M XECUTEs $ZINTERRUPT after completing
+ the commit or rollback. CTRAP characters are recognized when they are
+ typed on OpenVMS but when they are read on UNIX.
+
+ If an interrupt event occurs in a long running external call (for example,
+ waiting in a message queue), GT.M recognizes the event but makes the
+ vector transfer after the external call returns when it reaches the next
+ appropriate execution boundary.
+
+ When an interrupt handler is invoked, GT.M saves and restores the current
+ values of $REFERENCE. However, the current device ($IO) is neither saved
+ nor restored. If an interrupt handler changes $IO (via USE), ensure that
+ the interrupt handler restores the current device before returning. To
+ restore the device which was current when the interrupt handler began,
+ specify USE without any deviceparameters. Any attempt to do IO on a device
+ which was actively doing IO when the interrupt was recognized may result
+ in a ZINTERCURSEIO error.
+
+ Example:
+
+ set $zinterrupt="do ^interrupthandler($io)"
+
+ interrupthandler(currentdev)
+ do ^handleinterrupt ; handle the interrupt
+ use currentdev ; restore the device which was current when the interrupt was recognized
+ quit
+
+ The use of the INTRPT facility may create a temporary hang or pause while
+ the interrupt handler code is executed. For the default case where the
+ interrupt handler uses IF $ZJOBEXAM() to create a dump, the pause duration
+ depends on the number of local variables in the process at the time of the
+ dump and on the speed of the disk being written to. The dumps are slower
+ on a network-mounted disk than on a disk directly connected to the local
+ system. Any interrupt driven code should be designed to account for this
+ issue.
+
+ **Important**
+
+ Because sending an interrupt signal requires the sender to have
+ appropriate permissions, the use of the job interrupt facility itself does
+ not present any inherent security exposures. Nonetheless, because the dump
+ files created by the default action contain the values of every local
+ variable in the context at the time they are made, inappropriate access to
+ the dump files would constitute a security exposure. Make sure the design
+ and implementation of any interrupt logic includes careful consideration
+ to security issues.
+
+ During the execution of the interrupt handling code, $ZINITERRUPT
+ evaluates to 1 (TRUE).
+
+ If an error occurs while compiling the $ZINTERRUPT code, the error handler
+ is not invoked (the error handler is invoked if an error occurs while
+ executing the $ZINTERRUPT code), GT.M sends the GTM-ERRWZINTR message and
+ the compiler error message to the operator log facility. If the GT.M
+ process is at a direct mode prompt or is executing a direct mode command
+ (for example, a FOR loop), GT.M sends also sends the GTM-ERRWZINTR error
+ message to the user console along with the compilation error. In both
+ cases, the interrupted process resumes execution without performing any
+ action specified by the defective $ZINTERRUPT vector.
+
+ If GT.M encounters an error during creation of the interrupt handler's
+ stack frame (before transferring control to the application code specified
+ by the vector), that error is prefixed with a GTM-ERRWZINTR error. The
+ error handler then executes normal error processing associated with the
+ interrupted routine.
+
+ **Note**
+
+ The interrupt handler does not operate "outside" the current M environment
+ but rather within the environment of the process.
+
+ TP transaction is in progress (0<$TLEVEL), updates to globals are not safe
+ since a TP restart can be signaled at any time prior to the transaction
+ being committed - even after the interrupt handler returns. A TP restart
+ reverses all global updates and unwinds the M stack so it is as if the
+ interrupt never occurred. The interrupt handler is not redriven as part of
+ a transaction restart. Referencing (reading) globals inside an interrupt
+ handler can trigger a TP restart if a transaction is active. When
+ programming interrupt handling, either discard interrupts when 0<$TLEVEL
+ (forcing the interrupting party to try again), or use local variables that
+ are not restored by a TRESTART to defer the interrupt action until after
+ the final TCOMMIT.
+
+2 $ZINInterrupt
+ $ZINInterrupt
+
+ $ZINI[NTERRUPT] evaluates to 1 (TRUE) when a process is executing code
+ initiated by the interrupt mechanism, and otherwise 0 (FALSE).
+
+ GT.M does not permit the SET or NEW commands to modify $ZININTERRUPT.
+
+2 $ZIO
+ $ZIO
+
+ $ZIO contains the translated name of the current device, in contrast to
+ $IO, which contains the name as specified by the USE command.
+
+ GT.M does not permit the SET or NEW command to modify $ZIO.
+
+ An example where $ZIO contains a value different from $IO is if the
+ environment variable gtm_principal is defined.
+
+ Example:
+
+ $ gtm_principal="foo"
+ $ export gtm_principal
+ GTM>WRITE $IO
+ foo
+ GTM>WRITE $ZIO
+ /dev/pts/8
+
+ Notice that $ZIO contains the actual terminal device name while $IO
+ contains the string pointed to by the environment variable gtm_principal.
+
+2 $ZJob
+ $ZJob
+
+ $ZJ[OB] holds the pid of the process created by the last JOB command
+ performed by the current process.
+
+ GT.M initializes $ZJOB to zero (0) at process startup. If the JOB command
+ fails to spawn a new job, GT.M sets $ZJOB to zero (0). Note that because
+ of the left to right evaluation order of M, using $ZJOB in the
+ jobparameter string results in using the value created by the last, rather
+ than the current JOB command, which is not likely to match common coding
+ practice.
+
+ GT.M does not permit the SET or NEW command to modify $ZJOB.
+
+2 $ZKey
+ $ZKey
+
+ For Socket devices:
+
+ $ZKEY contains a list of sockets in the current SOCKET device which are
+ ready for use. Its contents include both non selected but ready sockets
+ from the prior WRITE /WAITs and any sockets with unread data in their GT.M
+ buffer. $ZKEY can be used any time a SOCKET device is current. Once an
+ incoming socket (that is, "LISTENING") has been accepted either by being
+ selected by WRITE /WAIT or by USE socdev:socket="listeningsocket", it is
+ removed from $ZKEY.
+
+ $ZKEY contains any one of the following values:
+
+ "LISTENING|<listening_socket_handle>|{<portnumber>|</path/to/LOCAL_socket>}"
+
+ "READ|<socket_handle>|<address>"
+
+ If $ZKEY contains one or more "READ|<socket_handle>|<address>" entries, it
+ means there are ready to READ sockets that were selected by WRITE /WAIT or
+ were partially read and there is data left in their buffer. Each entry is
+ delimited by a ";".
+
+ $ZKEY is empty if no sockets have data in the buffer and there are no
+ unaccepted incoming sockets from previous WRITE /WAITs.
+
+ For Sequential File Device:
+
+ $ZKEY contains the current position in the file based on the last READ.
+ This is in bytes for STREAM and VARIABLE formats, and in a record,byte
+ pair for FIXED format. For FIXED format, SEEKs and normal READs always
+ produce a zero byte position; a non-zero byte position in $ZKEY for FIXED
+ format operation indicates a partially read record, caused by a READ # or
+ READ *. In FIXED mode, the information returned for $ZKEY is a function of
+ record size, and, if a USE command changes record size by specifying the
+ WIDTH deviceparameter while the file is open, $ZKEY offsets change
+ accordingly; if record size changes, previously saved values of $ZKEY are
+ likely inappropriate for use with SEEK.
+
+2 $ZLevel
+ $ZLevel
+
+ $ZL[EVEL] contains an integer value indicating the "level of nesting"
+ caused by DO commands, XECUTE commands, and extrinsic functions in the M
+ invocation stack.
+
+ $ZLEVEL has an initial value of one (1) and increments by one with each
+ DO, XECUTE or extrinsic function. Any QUIT that does not terminate a FOR
+ loop decrements $ZLEVEL. ZGOTO may also reduce $ZLEVEL. In accordance with
+ the M standard, a FOR command does not increase $ZLEVEL. M routines cannot
+ modify $ZLEVEL with the SET or NEW commands.
+
+ Use $ZLEVEL in debugging or in an error-handling mechanism to capture a
+ level for later use in a ZGOTO argument.
+
+ Example:
+
+ GTM>zprint ^zleve
+ zleve;
+ do B
+ write X,!
+ quit
+ B
+ goto C
+ quit
+ C
+ do D
+ quit
+ D
+ set X=$ZLEVEL
+ quit
+
+ GTM>do ^zleve
+ 4
+
+ GTM>
+
+ This program, executed from Direct Mode, produces a value of 4 for
+ $ZLEVEL. If you run this program from the shell, the value of $ZLEVEL is
+ three (3).
+
+2 $ZMAXTPTIme
+ $ZMAXTPTIme
+
+ $ZMAXTPTI[ME] contains an integer value indicating the time duration GT.M
+ should wait for the completion of all activities fenced by the current
+ transaction's outermost TSTART/TCOMMIT pair.
+
+ $ZMAXTPTIME can be SET but cannot be NEWed.
+
+ $ZMAXTPTIME takes its value from the environment variable gtm_zmaxtptime.
+ If gtm_zmaxtptime is not defined, the initial value of $ZMAXTPTIME is zero
+ (0) seconds which indicates "no timeout" (unlimited time). The value of
+ $ZMAXTPTIME when a transaction's outermost TSTART operation executes
+ determines the timeout setting for that transaction.
+
+ When a $ZMAXTPTIME expires, GT.M executes the $ETRAP/$ZTRAP exception
+ handler currently in effect.
+
+ **Note**
+
+ Negative values of $ZMAXTPTIME are also treated as "no timeout". Timeouts
+ apply only to the outermost transaction, that is, $ZMAXTPTIME has no
+ effect when TSTART is nested within another transaction.
+
+ Example:
+
+ Test;testing TP timeouts
+ set $ZMAXTPTIME=6,^X=0,^Y=0,^Z=0
+ write "Start with $ZMAXTPTIME=",$ZMAXTPTIME,":",!
+ for sleep=3:2:9 do
+ . set retlvl=$zl
+ . do longtran;ztrap on longtran
+ ;continues execution
+ ;on next line
+ . write "(^X,^Y)=(",^X,",",^Y,")",!
+ write !,"Done TP Timeout test.",!
+ quit
+ longtran ;I/O in TP doesn't get rolled back
+ set newzt="set $ZT="""" ";avoid recursive ZTRAP
+ set $ZT=newzt_" goto err"
+ tstart ():serial ;plain tstart works as well
+ set ^X=1+^X
+ write !,"^X=",^X,",will set ^Y to ",sleep
+ write " in ",sleep," seconds..."
+ hang sleep
+ set ^Y=sleep
+ write "^Y=",^Y
+ tcommit
+ write "...committed.",!
+ quit
+ err;
+ set $ZT=""
+ write !,"In $ZTRAP handler. Error was: "
+ write !," ",$zstatus
+ if $TLEVEL do ;test allows handler use outside of TP
+ . trollback
+ . write "Rolled back transaction."
+ write !
+ zgoto retlvl
+
+ Results:
+
+ Start with $ZMAXTPTIME=6:
+
+ ^X=1,will set ^Y to 3 in 3 seconds...^Y=3...committed.
+
+ ^X=2,will set ^Y to 5 in 5 seconds...^Y=5...committed.
+
+ ^X=3,will set ^Y to 7 in 7 seconds...
+ In $ZTRAP handler. Error was:
+ 150377322,longtran+7^tptime,%GTM-E-TPTIMEOUT, Transaction timeoutRolled back transaction.
+
+ ^X=3,will set ^Y to 9 in 9 seconds...
+
+ In $ZTRAP handler. Error was:
+ 150377322,longtran+7^tptime,%GTM-E-TPTIMEOUT, Transaction timeoutRolled back transaction.
+
+ Done TP Timeout test.
+
+2 $ZMOde
+ $ZMOde
+
+ $ZMO[DE] contains a string value indicating the process execution mode.
+
+ The mode can be:
+
+ * INTERACTIVE
+ * OTHER
+
+ M routines cannot modify $ZMODE.
+
+ Example:
+
+ GTM>WRITE $ZMODE
+ INTERACTIVE
+
+ This displays the process mode.
+
+2 $ZONLNrlbk
+ $ZONLNrlbk
+
+ $ZONLNRLBK increments every time a process detects a concurrent MUPIP
+ JOURNAL -ONLINE -ROLLBACK.
+
+ GT.M initializes $ZONLNRLBK to zero (0) at process startup. GT.M does not
+ permit the SET or NEW commands to modify $ZONLNRLBK.
+
+2 $ZPATNumeric
+ $ZPATNumeric
+
+ $ZPATN[UMERIC] is a read-only intrinsic special variable that determines
+ how GT.M interprets the patcode "N" used in the pattern match operator.
+
+ With $ZPATNUMERIC="UTF-8", the patcode "N" matches any numeric character
+ as defined by UTF-8 encoding. With $ZPATNUMERIC="M", GT.M restricts the
+ patcode "N" to match only ASCII digits 0-9 (that is, ASCII 48-57). When a
+ process starts in UTF-8 mode, intrinsic special variable $ZPATNUMERIC
+ takes its value from the environment variable gtm_patnumeric. GT.M
+ initializes the intrinsic special variable $ZPATNUMERIC to "UTF-8" if the
+ environment variable gtm_patnumeric is defined to "UTF-8". If the
+ environment variable gtm_patnumeric is not defined or set to a value other
+ than "UTF-8", GT.M initializes $ZPATNUMERIC to "M".
+
+ GT.M populates $ZPATNUMERIC at process initialization from the environment
+ variable gtm_patnumeric and does not allow the process to change the
+ value.
+
+ For characters in Unicode, GT.M assigns patcodes based on the default
+ classification of the Unicode character set by the ICU library with three
+ adjustments:
+
+ 1. If $ZPATNUMERIC is not "UTF-8", non-ASCII decimal digits are
+ classified as A.
+ 2. Non-decimal numerics (Nl and No) are classified as A.
+ 3. The remaining characters (those not classified by ICU functions:
+ u_isalpha, u_isdigit, u_ispunct, u_iscntrl, 1), or 2) above) are
+ classified into either patcode P or C. The ICU function u_isprint is
+ used since is returns "TRUE" for non-control characters.
+
+ The following table contains the resulting Unicode general category to M
+ patcode mapping:
+
+ +------------------------------------------------------------------------+
+ | Unicode General Category | GT.M patcode Class |
+ |------------------------------+-----------------------------------------|
+ | L* (all letters) | A |
+ |------------------------------+-----------------------------------------|
+ | M* (all marks) | P |
+ |------------------------------+-----------------------------------------|
+ | Nd (decimal numbers) | N (if decimal digit is ASCII or |
+ | | $ZPATNUMERIC is "UTF-8", otherwise A |
+ |------------------------------+-----------------------------------------|
+ | Nl (letter numbers) | A (examples of Nl are Roman numerals) |
+ |------------------------------+-----------------------------------------|
+ | No (other numbers) | A (examples of No are fractions) |
+ |------------------------------+-----------------------------------------|
+ | P* (all punctuation) | P |
+ |------------------------------+-----------------------------------------|
+ | S* (all symbols) | P |
+ |------------------------------+-----------------------------------------|
+ | Zs (spaces) | P |
+ |------------------------------+-----------------------------------------|
+ | Zl (line separators) | C |
+ |------------------------------+-----------------------------------------|
+ | Zp (paragraph separators) | C |
+ |------------------------------+-----------------------------------------|
+ | C* (all control code points) | C |
+ +------------------------------------------------------------------------+
+
+ For a description of the Unicode general categories, refer to
+ http://unicode.org/charts/.
+
+ Example:
+
+ GTM>write $zpatnumeric
+ UTF-8
+ GTM>Write $Char($$FUNC^%HD("D67"))?.N ; This is the Malayalam decimal digit 1
+ 1
+ GTM>Write 1+$Char($$FUNC^%HD("D67"))
+ 1
+ GTM>Write 1+$Char($$FUNC^%HD("31")) ; This is the ASCII digit 1
+ 2
+
+2 $ZPOSition
+ $ZPOSition
+
+ $ZPOS[ITION] contains a string value specifying the current entryref,
+ where entryref is [label][+offset]^routine, and the offset is evaluated
+ from the closest preceding label.
+
+ GT.M does not permit the SET or NEW commands to modify $ZPOSITION.
+
+ Example:
+
+ GTM>WRITE !,$ZPOS,! ZPRINT @$ZPOS
+
+ This example displays the current location followed by the source code for
+ that line.
+
+2 $ZPROMpt
+ $ZPROMpt
+
+ $ZPROM[PT] contains a string value specifying the current Direct Mode
+ prompt. By default, GTM>is the Direct Mode prompt. M routines can modify
+ $ZPROMPT by means of a SET command. $ZPROMPT cannot exceed 16 characters.
+ If an attempt is made to assign $ZPROMPT to a longer string, only the
+ first 16 characters will be taken.
+
+ In UTF-8 mode, if the 31st byte is not the end of a valid UTF-8 character,
+ GT.M truncates the $ZPROMPT value at the end of last character that
+ completely fits within the 31 byte limit.
+
+ The environment gtm_prompt initializes $ZPROMPT at process startup.
+
+ Example:
+
+ GTM>set $zprompt="Test01">"
+ Test01>set $zprompt="GTM>"
+
+ This example changes the GT.M prompt to Test01> and then back to GTM>.
+
+2 $ZREalstor
+ $ZREalstor
+
+ $ZREALSTOR contains the total memory (in bytes) allocated by the GT.M
+ process, which may or may not actually be in use. It provides one view
+ (see also $ZALLOCSTOR and ZUSEDSTOR) of the process memory utilization and
+ can help identify storage related problems. GT.M does not permit
+ $ZREALSTOR to be SET or NEWed.
+
+2 $ZROutines
+ $ZROutines
+
+ $ZRO[UTINES] contains a string value specifying a directory or list of
+ directories containing object files. Each object directory may also have
+ an associated directory, or list of directories, containing the
+ corresponding source files. These directory lists are used by certain GT.M
+ functions, primarily auto-ZLINK, to locate object and source files. The
+ order in which directories appear in a given list determines the order in
+ which they are searched for the appropriate item.
+
+ Searches that use $ZROUTINES treat files as either object or source files.
+ GT.M treats files with an extension of .o as object files and files with
+ an extension of .m as source files.
+
+ **Note**
+
+ Paths used in $ZROUTINES to locate routines must not include embedded
+ spaces, as $ZROUTINES uses spaces as delimiters.
+
+3 Establishing_the_Value_from_$gtmroutines
+ Establishing the Value from $gtmroutines
+
+ When the environment variable gtmroutines is defined, GT.M initializes
+ $ZROUTINES to the value of gtmroutines. Otherwise, GT.M initializes
+ $ZROUTINES to a null value. When $ZROUTINES is null, GT.M attempts to
+ locate all source and object files in the current working directory.
+ $ZROUTINES="" is equivalent to $ZROUTINES=".".
+
+ Commands or functions such as DO, GOTO, ZGOTO, ZBREAK, ZPRINT, and $TEXT
+ may auto-ZLINK and thereby indirectly use $ZROUTINES. If their argument
+ does not specify a directory, ZEDIT and explicit ZLINK use $ZROUTINES.
+ ZPRINT and $TEXT use $ZROUTINES to locate a source file if GT.M cannot
+ find the source file pointed to by the object file.
+
+3 Setting_a_Value_for_$ZROutines
+ Setting a Value for $ZROutines
+
+ $ZRO[UTINES] is a read-write Intrinsic Special Variable, so M can also SET
+ the value.
+
+ By default, each directory entry in $ZROUTINES is assumed to contain both
+ object and source files. However, each object directory may have an
+ associated directory or list of directories to search for the
+ corresponding source files. This is done by specifying the source
+ directory list, in parentheses, following the object directory
+ specification.
+
+ If the command specifies more than one source directory for an object
+ directory, the source directories must be separated by spaces, and the
+ entire list must be enclosed in parentheses ( ) following the object
+ directory-specification. If the object directory should also be searched
+ for source, the name of that directory must be included in the
+ parentheses, (usually as the first element in the list).
+ Directory-specifications may also include empty parentheses, directing
+ GT.M to proceed as if no source files exist for objects located in the
+ qualified directory.
+
+ To set $ZROUTINES outside of M, use the appropriate shell command to set
+ gtmroutines. Because gtmroutines is a list, enclose the value in quotation
+ marks (" ").
+
+ Changes to the value of $ZROUTINES during a GT.M invocation only last for
+ the current invocation, and do not change the value of gtmroutines.
+
+ Directory specifications may include an environment variable. When GT.M
+ SETs $ZROUTINES, it translates all environment variables and verifies the
+ syntax and the existence of all specified directories. If $ZROUTINES is
+ set to an invalid value, GT.M generates a run-time error and does not
+ change the value of $ZROUTINES. Because the environment variables are
+ translated when $ZROUTINES is set, any changes to their definition have no
+ effect until $ZROUTINES is set again.
+
+3 $ZROutines_Examples
+ $ZROutines Examples
+
+ Example:
+
+ GTM>s $zroutines=".(../src) $gtm_dist"
+
+ This example directs GTM to look for object modules first in your current
+ directory, then in the distribution directory that contains the percent
+ routines. GT.M locates sources for objects in your current directory in
+ the sibling /src directory.
+
+ Example:
+
+ $ gtmroutines="/usr/jones /usr/smith"
+ $ export gtmroutines
+ $ gtm
+ GTM>write $zroutines
+ "/usr/jones /usr/smith"
+ GTM>set $zro="/usr/jones/utl /usr/smith/utl"
+ GTM>write $zroutines
+ "/usr/jones/utl /usr/smith/utl"
+ GTM>halt
+ $ echo $gtmroutines
+ /usr/jones /usr/smith
+
+ This example defines the environment variable gtmroutines. Upon entering
+ GT.M Direct Mode $zroutines has the value supplied by gtmroutines. The SET
+ command changes the value. When the GT.M image terminates, the shell echo
+ command demonstrates that gtmroutines has not been modified by the M SET
+ command.
+
+ Example:
+
+ GTM>SET $ZRO=". /usr/smith"
+
+ This example sets $zroutines to a list containing two directories.
+
+ Example:
+
+ GTM>set $zro="/usr/smith(/usr/smith/tax /usr/smith/fica)"
+
+ This example specifies that GT.M should search the directory /usr/smith
+ for object files, and the directories /usr/smith/tax and /usr/smith/fica
+ for source files. Note that in this example. GT.M does not search
+ /usr/smith for source files.
+
+ Example:
+
+ GTM>set $zro="/usr/smith(/usr/smith /usr/smith/tax /usr/smith/fica)"
+
+ This example specifies that GT.M should search the directory /usr/smith
+ for object files and the directories /usr/smith/tax and /usr/smith/fica
+ for source files. Note that the difference between this example and the
+ previous one is that GT.M searches /usr/smith for both object and source
+ files.
+
+ Example:
+
+ GTM>set $zro="/usr/smith /usr/smith/tax() /usr/smith/fica"
+
+ This specifies that GT.M should search /usr/smith and /usr/smith/fica for
+ object and source files. However, because the empty parentheses indicate
+ directories searched only for object files, GT.M does not search
+ /usr/smith/tax for source files.
+
+ Omitting the parentheses indicates that GT.M can search the directory for
+ both source and object files. $ZROUTINES=/usr/smith is equivalent to
+ $ZROUTINES=/usr/smith(/usr/smith).
+
+3 $ZROutines_Search_Types
+ $ZROutines Search Types
+
+ GT.M uses $ZRO[UTINES] to perform three types of searches:
+
+ * Object-only when the command or function using $ZROUTINES requires a
+ .o file extension.
+ * Source-only when the command or function using $ZROUTINES requires a
+ file extension other than .o.
+ * Object-source match when the command or function using $ZROUTINES does
+ not specify a file extension.
+
+ An explicit ZLINK that specifies a non .OBJ .o extension is considered as
+ a function that has not specified a file extension for the above searching
+ purposes.
+
+ All searches proceed from left to right through $ZROUTINES. By default,
+ GT.M searches directories for both source and object files. GT.M searches
+ directories followed by empty parentheses ( ) for object files only. GT.M
+ searches directories in parentheses only for source files.
+
+ Once an object-matching search locates an object file, the source search
+ becomes limited. If the directory containing the object file has an
+ attached parenthetical list of directories, GT.M only searches the
+ directories in the attached list for matching source files. If the
+ directory containing the object files does not have following parentheses,
+ GT.M restricts the search for matching source files to the same directory.
+ If the object module is in a directory qualified by empty parentheses,
+ GT.M cannot perform any operation that refers to the source file.
+
+ The following table shows GT.M commands and functions using $ZROUTINES and
+ the search types they support.
+
+ +------------------------------------------------------+
+ | GT.M Commands and $ZROUTINES Search Types |
+ |------------------------------------------------------|
+ | SEARCH/ | FILE | |
+ | FUNCTION | EXTENSION | SEARCH TYPE |
+ | | SPECIFIED | |
+ |------------+-----------+-----------------------------|
+ | | | OBJ-ONLY | SRC-ONLY | MATCH |
+ |------------+-----------+----------+----------+-------|
+ | EXPLICIT | | | | |
+ | | .o | X | | |
+ | ZLINK | | | | |
+ |------------+-----------+----------+----------+-------|
+ | | Not .o | | | X |
+ |------------+-----------+----------+----------+-------|
+ | | None | | | X |
+ |------------+-----------+----------+----------+-------|
+ | AUTO-ZLINK | None | | | X |
+ |------------+-----------+----------+----------+-------|
+ | ZEDIT | Not .o | | X | |
+ |------------+-----------+----------+----------+-------|
+ | ZPRINT | None | | X | |
+ |------------+-----------+----------+----------+-------|
+ | $TEXT | None | | X | |
+ +------------------------------------------------------+
+
+ If ZPRINT or $TEXT() require a source module for a routine that is not in
+ the current image, GT.M first performs an auto-ZLINK with a matching
+ search.
+
+ ZPRINT or $TEXT locate the source module using a file specification for
+ the source file located in the object module. If GT.M finds the source
+ module in the directory where it was when it was compiled, the run-time
+ system does not use $ZROUTINES. If GT.M cannot find the source file in the
+ indicated location, the run-time system uses $ZROUTINES.
+
+3 $ZROutines_Search_Examples
+ $ZROutines Search Examples
+
+ This section describes a model for understanding $ZROUTINES operations and
+ the illustrating examples, which may assist you if you wish to examine the
+ topic closely.
+
+ You may think of $ZROUTINES as supplying a two dimensional matrix of
+ places to look for files. The matrix has one or more rows. The first row
+ in the matrix contains places to look for object and the second and
+ following rows contain places to look for source. Each column represents
+ the set of places that contain information related to the object modules
+ in the first row of the column.
+
+ Example:
+
+ GTM>s $zro=". /usr/smi/utl() /usr/jon/utl
+ (/usr/jon/utl/so /usr/smi/utl)"
+
+ The following table illustrates the matrix view of this $ZROUTINES.
+
+ +--------------------------------------------------------+
+ | $ZROUTINES Search Matrix |
+ |--------------------------------------------------------|
+ | SEARCH FOR | Column 1 | Column 2 | Column 3 |
+ |------------+----------+--------------+-----------------|
+ | OBJECTS | . | /usr/smi/utl | /usr/jon/utl |
+ |------------+----------+--------------+-----------------|
+ | SOURCE | . | | /usr/jon/utl/so |
+ |------------+----------+--------------+-----------------|
+ | | | | /usr/smi/utl |
+ +--------------------------------------------------------+
+
+ To perform object-only searches, GT.M searches only the directories or
+ object libraries in the top 'objects' row for each column starting at
+ column one. If GT.M does not locate the object file in a directory or
+ object library in the 'objects' row of a column, GT.M begins searching
+ again in the next column. If GT.M cannot locate the file in any of the
+ columns, it issues a run-time error.
+
+ As illustrated in the preceding table, GT.M searches for object files in
+ the directories . ,/usr/smi/utl and /usr/jon/utl.
+
+ To perform source-only searches, GT.M looks down to the 'source' row at
+ the bottom of each column, excluding columns headed by object-only
+ directories (that is, those object directories, which consist of an empty
+ list of source directories) or object libraries. If GT.M cannot locate the
+ source file in the 'source' row of a column, it searches the next eligible
+ column.
+
+ To perform object-source match searches, GT.M looks at each column
+ starting at column one. GT.M does an object-only search in the 'objects'
+ row of a column and a source-only search in the 'source' row(s) of a
+ column. If GT.M locates either the object-file or the souce-file, the
+ search is completed. Else, GT.M starts searching the next column. If GT.M
+ cannot locate either the object file or the source file in any of the
+ columns, it issues a run-time error.
+
+ As illustrated in the preceding table, GT.M searches for source-files in
+ the directory "." in column one. If GT.M cannot locate the source file in
+ ".", it omits column two because it is an object-only directory and
+ instead searches column three. Since column three specifies
+ /usr/jon/utl/so and /usr/smi/utl, GT.M searches for the source-file in
+ these directories in column three and not in /usr/jon/utl. If GT.M cannot
+ locate the source-file in column three, it terminates the search and
+ issues a run-time error.
+
+ Once the object-source match search is done, GT.M now has either the
+ object-file or source-file or both available. GT.M then recompiles the
+ source-file based on certain conditions, before linking the object-file
+ into the current image.
+
+ If auto-ZLINK or ZLINK determines that the source file requires
+ [re]compilation, GT.M places the object file in the above object directory
+ in the same column as the source file. For example, if GT.M locates the
+ source file in /usr/smi/utl in column three, GT.M places the resultant
+ object file in /usr/jon/utl.
+
+3 Shared_Library_File_Specification_in_$ZROUTINES
+ Shared Library File Specification in $ZROUTINES
+
+ The $ZROUTINES ISV allows individual UNIX shared library file names to be
+ specified in the search path. During a search for auto-ZLINK, when a
+ shared library is encountered, it is probed for a given routine and, if
+ found, that routine is linked/loaded into the image. During an explicit
+ ZLINK, all shared libraries in $ZROUTINES are ignored and are not searched
+ for a given routine.
+
+ $ZROUTINES syntax contains a file-specification indicating shared library
+ file path. GT.M does not require any designated extension for the shared
+ library component of $ZROUTINES. Any file specification that does not name
+ a directory is treated as shared library. However, it is recommended that
+ the extension commonly used on a given platform for shared library files
+ be given to any GT.M shared libraries. A shared library component cannot
+ specify source directories. GT.M reports an error at an attempt to
+ associate any source directory with a shared library in $ZROUTINES.
+
+ The following traits of $ZROUTINES help support shared libraries:
+
+ * The $ZROUTINES search continues to find objects in the first place,
+ processing from left to right, that holds a copy; it ignores any
+ copies in subsequent locations. However, now for auto-ZLINK, shared
+ libraries are accepted as object repositories with the same ability to
+ supply objects as directories.
+ * Explicit ZLINK, never searches Shared Libraries. This is because
+ explicit ZLINK is used to link a newly created routine or re-link a
+ modified routine and there is no mechanism to load new objects into an
+ active shared library.
+ * ZPRINT and $TEXT() of the routines in a shared library, read source
+ file path from the header of the loaded routine. If the image does not
+ contain the routine, an auto-ZLINK is initiated. If the source file
+ path recorded in the routine header when the module was compiled
+ cannot be located, ZPRINT and $TEXT() initiate a search from the
+ beginning of $ZROUTINES, skipping over the shared library file
+ specifications. If the located source does not match the code in image
+ (checked via checksum), ZPRINT generates an object-source mismatch
+ status and $TEXT() returns a null string.
+ * ZEDIT, when searching $ZROUTINES, skips shared libraries like explicit
+ ZLINK for the same reasons. $ZSOURCE ISV is implicitly set to the
+ appropriate source file.
+
+ For example, if libshare.so is built with foo.o compiled from
+ ./shrsrc/foo.m, the following commands specify that GT.M should search the
+ library ./libshare.so for symbol foo when do ^foo is encountered.
+
+ GTM>SET $ZROUTINES="./libshare.so ./obj(./shrsrc)"
+ GTM>DO ^foo;auto-ZLINK foo - shared
+ GTM>ZEDIT "foo";edit ./shrsrc/foo.m
+ GTM>W $ZSOURCE,!;prints foo
+ GTM>ZPRINT +0^foo;issues a source-object mismatch status TXTSRCMAT error message
+ GTM>ZLINK "foo";re-compile ./shrsrc/foo.m to generate ./obj/foo.o.
+ GTM>W $TEXT(+0^foo);prints foo
+
+ Note that ZPRINT reports an error, as foo.m does not match the routine
+ already linked into image. Also note that, to recompile and re-link the
+ ZEDITed foo.m, its source directory needs to be attached to the object
+ directory [./obj] in $ZROUTINES. The example assumes the shared library
+ (libshare.so) has been built using shell commands.
+
+2 $ZSOurce
+ $ZSOurce
+
+ $ZSO[URCE] contains a string value specifying the default pathname for the
+ ZEDIT and ZLINK commands. ZEDIT or ZLINK without an argument is equivalent
+ to ZEDIT/ZLINK $ZSOURCE.
+
+ $ZSOURCE initially contains the null string. When ZEDIT and ZLINK commands
+ have a pathname for an argument, they implicitly set $ZSOURCE to that
+ argument. This ZEDIT/ZLINK argument can include a full pathname or a
+ relative one. A relative path could include a file in the current
+ directory, or the path to the file from the current working directory. In
+ the latter instance, do not include the slash before the first directory
+ name. $ZSOURCE will prefix the path to the current working directory
+ including that slash.
+
+ The file name may contain a file extension. If the extension is .m or .o,
+ $ZSOURCE drops it. The ZEDIT command accepts arguments with extensions
+ other than .m or .o. $ZSOURCE retains the extension when such arguments
+ are passed.
+
+ If $ZSOURCE contains a file with an extension other than .m or .o, ZEDIT
+ processes it but ZLINK returns an error message
+
+ $ZSOURCE is a read-write Intrinsic Special Variable, (i.e., it can appear
+ on the left side of the equal sign (=) in the argument to the SET
+ command). A $ZSOURCE value may include an environment variable. GT.M
+ handles logical names that translate to other logical names by performing
+ iterative translations according to VMS conventions. If a logical name
+ translates to a VMS search list, GT.M uses only the first name in the
+ list.
+
+ Example:
+
+ GTM>ZEDIT "subr.m"
+ .
+ .
+ GTM>WRITE $ZSOURCE
+
+ subr
+
+ Example:
+
+ GTM>ZEDIT "test"
+ .
+ .
+ .
+ GTM>WRITE $ZSOURCE
+
+ "test"
+
+ Example:
+
+ GTM>ZEDIT "/usr/smith/report.txt"
+ .
+ .
+ .
+ GTM>WRITE $ZSOURCE
+
+ /usr/smith/report.txt
+
+ Example:
+
+ GTM>ZLINK "BASE.O"
+ .
+ .
+ .
+ GTM>WRITE $ZSOURCE
+ BASE
+
+2 $ZStatus
+ $ZStatus
+
+ $ZS[TATUS] contains a string value specifying the error condition code and
+ location of the last exception condition that occurred during routine
+ execution.
+
+ GT.M maintains $ZSTATUS as a string consisting of three or more
+ substrings. The string consists of the following:
+
+ Format: %<FAC>-<SEV>-<ID>, <TEXT>
+ Example: %GTM-E-DIVZERO, Attempt to divide by zero
+
+ GT.M sets $ZSTATUS when it encounters errors during program execution, but
+ not when it encounters errors in a Direct Mode command.
+
+ $ZSTATUS is a read-write Intrinsic Special Variable, (i.e., it can occur
+ on the left side of the equal sign (=) in the argument to the SET
+ command). While it will accept any string, FIS recommends setting it to
+ null. M routines cannot modify $ZSTATUS with the NEW command.
+
+ Example:
+
+ GTM>WRITE $ZSTATUS
+ 150373110,+1^MYFILE,%GTM-E-DIVZERO,
+ Attempt to divide by zero
+
+ This example displays the status generated by a divide by zero (0).
+
+2 $ZSTep
+ $ZSTep
+
+ $ZST[EP] contains a string value specifying the default action for the
+ ZSTEP command. $ZSTEP provides the ZSTEP action only when the ZSTEP
+ command does not specify an action.
+
+ $ZSTEP initially contains the string "B" to enter direct mode. $ZSTEP is a
+ read-write Intrinsic Special Variable, (i.e., it can appear on the left
+ side of the equal sign (=) in the argument to the SET command).
+
+ Example:
+
+ GTM>WRITE $ZSTEP
+ B
+ GTM>
+
+ This example displays the current value of $ZSTEP, which is the default.
+
+ Example:
+
+ GTM>SET $ZSTEP="ZP @$ZPOS B"
+
+ This example sets $ZSTEP to code that displays the contents of the next
+ line to execute, and then enters Direct Mode.
+
+2 $ZSYstem
+ $ZSYstem
+
+ $ZSY[STEM] holds the value of the status code for the last subprocess
+ invoked with the ZSYSTEM command.
+
+2 $ZTExit
+ $ZTExit
+
+ $ZTE[XIT] contains a string value that controls the GT.M interrupt
+ facility at the transaction commit or rollback. At each outermost TCOMMIT
+ or TROLLBACK, If +$ZTEXIT evaluates to non-zero (TRUE), then $ZINTERRUPT
+ is XECUTEd after completing the commit or rollback.
+
+ $ZTEXIT is a read-write ISV, that is, it can appear on the left side of
+ the equal sign (=) in the argument to the SET command. M routines cannot
+ NEW $ZTEXIT. GT.M initializes $ZTEXIT to null at the process startup. Note
+ that the changes to the value of $ZTEXIT during a GT.M invocation last for
+ the entire duration of the process, so it is the application's
+ responsibility to reset $ZTEXIT after $ZINTERRUPT is delivered in order to
+ turn off redelivering the interrupt every subsequent transaction commit or
+ rollback.
+
+ Example:
+
+ $ export sigusrval=10
+ $ /usr/lib/fis-gtm/V6.1-000_x86_64/gtm
+
+ GTM>zprint ^ztran
+ foo;
+ set $ztexit=1
+ set $zinterrupt="d ^throwint"
+ tstart ()
+ for i=1:1:10 do
+ . set ^ACN(i,"bal")=i*100
+ tstart ()
+ do ^throwint
+ ;do ^proc
+ tcommit:$tlevel=2
+ for i=1:1:10 do
+ . set ^ACN(i,"int")=i*0.05
+ ;do ^srv
+ if $tlevel trollback
+ ;do ^exc
+ set $ztexit="",$zinterrupt=""
+ quit
+ bar;
+ write "Begin Transaction",!
+ set $ztexit=1
+ tstart ()
+ i '$zsigproc($j,$ztrnlnm("sigusrval")) write "interrupt sent...",!!
+ for i=1:1:4 set ^B(i)=i*i
+ tcommit
+ write "End Transaction",!
+ ;do ^srv
+ quit
+
+ GTM>zprint ^throwint
+ throwint
+ set $zinterrupt="write !,""interrupt occurred at : "",$stack($stack-1,""PLACE""),! set $ztexit=1"
+ if '$zsigproc($job,$ztrnlnm("sigusrval")) write "interrupt sent to process"
+ write "***************************************",!!
+ quit
+
+ GTM>do foo^ztran
+ interrupt sent to process
+ interrupt occurred at : throwint+3^throwint
+ ***************************************
+
+ interrupt occurred at : foo+13^ztran
+ GTM>
+
+ In the above call to foo^ztran, the interrupt handler is a user-defined
+ routine, throwint. The process is sent a signal (SIGUSR1), and $ZINTERRUPT
+ is executed. At the outermost trollback, the interrupt is rethrown,
+ causing $ZINTERRUPT to be executed again.
+
+ Example:
+
+ GTM>w $zinterrupt
+ "IF $ZJOBEXAM()"
+ GTM>zsystem "ls GTM*"
+ ls: No match.
+
+ GTM>do bar^ztran
+ Begin Transaction
+ interrupt sent...
+
+ End Transaction
+
+ GTM>zsystem "ls GTM*"
+ GTM_JOBEXAM.ZSHOW_DMP_3951_1 GTM_JOBEXAM.ZSHOW_DMP_3951_2
+
+ GTM>
+
+ This uses the default value of $ZINTERRUPT to service interrupts issued to
+ the process. The $ZJOBEXAM function executes a ZSHOW "*", and stores the
+ output in each GTM_ZJOBEXAM_ZSHOW_DMP for the initial interrupt, and at
+ tcommit when the interrupt is rethrown.
+
+2 $ZTrap
+ $ZTrap
+
+ $ZT[RAP] contains a string value that GT.M XECUTEs when an error occurs
+ during routine execution.
+
+ **Note**
+
+ The following discussion assumes that $ETRAP error handling is
+ simultaneously not in effect (that is, $ETRAP="").
+
+ When the $ZTRAP variable is not null, GT.M executes $ZTRAP at the current
+ level. The $ZTRAP variable has the initial value of "B," and puts the
+ process in Direct Mode when an error condition occurs. If the value of
+ $ZTRAP is null (""), an exception causes the image to run-down with the
+ condition code associated with the exception. If $ZTRAP contains invalid
+ source code, GT.M displays an error message and puts the process into
+ Direct Mode.
+
+ $ZTRAP is a read-write Intrinsic Special Variable, (that is, it can appear
+ on the left side of the equal sign (=) in the argument to the SET
+ command).
+
+ $ZTRAP may also appear as an argument to an inclusive NEW command. NEW
+ $ZTRAP causes GT.M to set $ETRAP or $ZTRAP, whichever is active, to null
+ ($ETRAP="" or $ZTRAP="") and stack its old value. The NEW command puts the
+ target ISV in control for error handling. When the program QUITs from the
+ invocation level where the NEW occurred, GT.M restores the value
+ previously stacked by the NEW. NEW $ZTRAP provides nesting of $ZTRAP.
+ Because $ZTRAP="" terminates the image when an error occurs, SET $ZTRAP=
+ generally follows immediately after NEW $ZTRAP. You may use this technique
+ to construct error handling strategies corresponding to the nesting of
+ your programs. If the environment variable gtm_ztrap_new evaluates to
+ boolean TRUE (case insensitive string "TRUE", or case insensitive string
+ "YES", or a non-zero number), $ZTRAP is NEWed when $ZTRAP is SET;
+ otherwise $ZTRAP is not stacked when it is SET.
+
+ **Note**
+
+ QUIT from a $ZTRAP terminates the level at which the $ZTRAP was activated.
+
+ Keep $ZTRAP simple and put complicated logic in another routine. If the
+ action specified by $ZTRAP results in another run-time error before
+ changing the value of $ZTRAP, GT.M invokes $ZTRAP until it exhausts the
+ process stack space, terminating the image. Carefully debug exception
+ handling. For more information on error handling, refer "Error
+ Processing".
+
+ Example:
+
+ GTM>S $ZTRAP="ZP @$ZPOS B"
+
+ This example modifies $ZTRAP to display source code for the line where
+ GT.M encounters an error before entering Direct Mode.
+
+ There are four settings of $ZTRAP controlled by the UNIX environment
+ variable gtm_ztrap_form.
+
+ The four settings of gtm_ztrap_form are:
+
+ * code - If gtm_ztrap_form evaluates to "code" (or a value that is not
+ one of the subsequently described values), then GT.M treats $ZTRAP as
+ code and handles it as previously described in the documentation.
+ * entryref - If gtm_ztrap_form evaluates to "entryref" then GT.M treats
+ it as an entryref argument to an implicit GOTO command.
+ * adaptive - If gtm_ztrap_form evaluates to "adaptive" then if $ZTRAP
+ does not compile to valid M code, then $ZTRAP is treated as just
+ described for "entryref." Since there is little ambiguity, code and
+ entryref forms of $ZTRAP can be intermixed in the same application.
+
+ **Important**
+
+ GT.M attempts to compile $ZTRAP before evaluating $ZTRAP as an
+ entryref. Because GT.M allows commands without arguments such as QUIT,
+ ZGOTO, or HANG as valid labels, be careful not to use such keywords as
+ labels for error handling code in "adaptive" mode.
+
+ * pope[ntryref] / popa[daptive] - If gtm_ztrap_form evaluates to
+ "POPE[NTRYREF]" or "POPA[DAPTIVE]" (case insensitive) and $ZTRAP value
+ is in the form of entryref, GT.M unwinds the M stack from the level at
+ which an error occurred to (but not including) the level at which
+ $ZTRAP was last SET. Then, GT.M transfers control to the entryref in
+ $ZTRAP at the level where the $ZTRAP value was SET. If the UNIX
+ environment variable gtm_zyerror is defined to a valid entryref, GT.M
+ transfers control to the entryref specified by GTM_ZYERROR (with an
+ implicit DO) after unwinding the stack and before transferring control
+ to the entyref specified in $ZTRAP.
+
+ **Note**
+
+ Like $ZTRAP values, invocation of device EXCEPTION values follow the
+ pattern specified by the current gtm_ztrap_form setting.
+
+2 $ZUSedstor
+ $ZUSedstor
+
+ $ZUSEDSTOR is the value in $ZALLOCSTOR minus storage management overhead
+ and represents the actual memory, in bytes, requested by current
+ activities. It provides one view (see also $ZALLOCSTOR and $ZREALSTOR) of
+ the process memory utilization and can help identify storage related
+ problems. GT.M does not permit $ZUSEDSTOR to be SET or NEWed.
+
+2 $ZVersion
+ $ZVersion
+
+ $ZV[ERSION] contains a string value specifying the currently installed
+ GT.M. $ZV[ERSION] is a space-delimited string with four pieces as follows:
+
+ <product> <release> <OS> <architecture>
+
+ o <product> is always "GT.M".
+ o <release> always begins with "V", and has the structure
+ V<DB_Format>.<major_release>-<minor_release>[<bug_fix_level>] where:
+
+ o <DB_Format> identifies the block format of GT.M database files
+ compatible with the release. For example, V4, V5, and V6. The
+ <DB_Format> piece in $ZVERSION does not change even when a MUPIP
+ UPRGRADE or MUPIP DOWNGRADE changes the DB Format element in the
+ database fileheader.
+ o <major_release> identifies a release with major enhancements.
+ o <minor_release> identifies minor enhancements to a major release.
+ The classification of major and minor enhancements is at the
+ discretion of FIS.
+ o An optional <bug_fix_level> is an upper-case letter indicating
+ bug fixes but no new enhancements. Note that GT.M is built
+ monolithically and never patched. Even though a bug fix release
+ has only bug fixes, it should be treated as a new GT.M release
+ and installed in a separate directory.
+
+ o <OS> is the host operating system name.
+ o <architecture> is the hardware architecture for which the release of
+ GT.M is compiled. Note that GT.M retains it original names for
+ continuity even if vendor branding changes, for example, "RS6000".
+
+ M routines cannot modify $ZVERSION.
+
+ Example:
+
+ GTM>w $zversion
+ GT.M V6.0-003 Linux x86_64
+
+ This example displays the current version identifier for GT.M.
+
+2 $ZYERror
+ $ZYERror
+
+ $ZYER[ROR] is a read/write ISV that contains a string value pointing to an
+ entryref. After GT.M encounters an error, if $ZYERROR is set a non-null
+ value, GT.M invokes the routine at the entryref specified by $ZYERROR with
+ an implicit DO. It is intended that the code invoked by $ZYERROR use the
+ value of $ZSTATUS to select or construct a value to which it SETs $ZERROR.
+ If $ZYERROR is not a valid entryref or if an error occurs while executing
+ the entryref specified by $ZYERROR, GT.M SETs $ZERROR to the error status
+ encountered. GT.M then returns control to the M code specified by
+ $ETRAP/$ZTRAP or device EXCEPTION.
+
+ $ZYERROR is implicitly NEWed on entry to the routine specified by
+ $ZYERROR. However, if GT.M fails to compile, GT.M does not transfer
+ control to the entryref specified by $ZYERROR.
+
+ GT.M permits $ZYERROR to be modified by the SET and NEW commands.
+
+2 Triggers_ISVs
+ Triggers ISVs
+
+ GT.M provides nine ISVs (Intrinsic Special Variables) to facilitate
+ trigger operations. With the exception of $ZTWORMHOLE, all numeric
+ trigger-related ISVs return zero (0) outside of a trigger context;
+ non-numeric ISVs return the empty string.
+
+3 $ZTDAta
+ $ZTDAta
+
+ Within trigger context, $ZTDATA returns $DATA(@$REFERENCE)#2 for a SET or
+ $DATA(@$REFERENCE) for a KILL, ZKILL or ZWITHDRAW prior to the explicit
+ update. This provides a fast path alternative, avoiding the need for
+ indirection in trigger code, to help trigger code determine the
+ characteristics of the triggering node prior to the triggering update. For
+ a SET, it shows whether the node did or did not hold data - whether a SET
+ is modifying the contents of an existing node or creating data at a new
+ node. For a KILL it shows whether the node had descendants and whether it
+ had data.
+
+3 $ZTLevel
+ $ZTLevel
+
+ Within trigger context, $ZTLEVEL returns the current level of trigger
+ nesting (invocation by a trigger of an additional trigger by an update in
+ trigger context).
+
+ $ZTLEVEL greater than one (>1) indicates that there are nested triggers in
+ progress. When a single update invokes multiple triggers solely because of
+ multiple trigger matches of that initial (non-trigger) update, they are
+ not nested (they are chained) and thus all have same $ZTLEVEL.
+
+ Example:
+
+ +^Cycle(1) -commands=Set -xecute="Write ""$ZTLevel for ^Cycle(1) is: "",$ZTLevel Set ^Cycle(2)=1"
+ +^Cycle(2) -commands=Set -xecute="Write ""$ZTLevel for ^Cycle(2) is: "",$ZTLevel Set ^Cycle(1)=1"
+
+ These trigger definitions show different values of $ZTLEVEL when two
+ triggers are called recursively (and pathologically).
+
+ +^Acct("ID") -commands=set -xecute="set ^Acct(1)=$ztvalue+1"
+ +^Acct(sub=:) -command=set -xecute="set ^X($ztvalue)=sub"
+
+ SET ^Acct("ID")=10 invokes both the above triggers in some order and
+ $ZTLEVEL will have the same value in both because these triggers are
+ chained rather than nested.
+
+3 $ZTNAME
+ $ZTNAME
+
+ Within a trigger context, $ZTNAME returns the trigger name. Outside a
+ trigger context, $ZTNAME returns an empty string.
+
+3 $ZTOLdval
+ $ZTOLdval
+
+ Within trigger context, $ZTOLDVAL returns the prior (old) value of the
+ global node whose update caused the trigger invocation. This provides a
+ fast path alternative to $GET(@$REFERENCE) at trigger entry (which avoids
+ the heavyweight indirection ). If there are multiple triggers matching the
+ same node (chained), $ZTOLDVAL returns the same result for each of them.
+
+ Example:
+
+ +^Acct(1,"ID") -commands=Set -xecute="Write:$ZTOLdval ""The prior value of ^Acct(1,ID) was: "",$ZTOLdval"
+
+ This trigger gets invoked with a SET and displays the prior value (if it
+ exists) of ^Acct(1,"ID").
+
+ GTM>w ^Acct(1,"ID")
+ 1975
+ GTM>s ^Acct(1,"ID")=2011
+ The prior value of ^Acct(1,ID) was: 1975
+
+3 $ZTRIggerop
+ $ZTRIggerop
+
+ Within trigger context, for SET (including MERGE and $INCREMENT()
+ operations), $ZTRIGGEROP has the value "S". For KILL, $ZTRIGGEROP has the
+ value "K" For ZKILL or ZWITHDRAW, $ZTRIGGEROP has the value "ZK".
+
+3 $ZTSlate
+ $ZTSlate
+
+ $ZTSLATE allows you to specify a string that you want to make available in
+ chained or nested triggers invoked for an outermost transaction (when a
+ TSTART takes $TLEVEL from 0 to 1). You might use $ZTSLATE to accumulate
+ transaction-related information, for example $ZTOLDVAL and $ZTVALUE,
+ available within trigger context for use in a subsequent trigger later in
+ the same transaction. For example, you can use $ZTSLATE to build up an
+ application history or journal record to be written when a transaction is
+ about to commit.
+
+ You can SET $ZTSLATE only while a database trigger is active. GT.M clears
+ $ZTSLATE for the outermost transaction or on a TRESTART. However, GT.M
+ retains $ZTSLATE for all sub-transactions (where $TLEVEL>1).
+
+ Example:
+
+ TSTART () ; Implicitly clears $ZTSLAT
+ SET ^ACC(ACN1,BAL)=AMT ; Trigger sets $ZTSLATE=ACN_"|"
+ SET ^ACC(ACN2,BAL)=-AMT ; Trigger sets $ZTSLATE=$ZTSLATE_ACN_"|"
+ ZTRIGGER ^ACT("TRANS") ; Trigger uses $ZTSLATE to update transaction log
+ TCOMMIT
+
+3 $ZTUPdate
+ $ZTUPdate
+
+ Within trigger context, for SET commands where the GT.M trigger specifies
+ a piece separator, $ZTUPDATE provides a comma separated list of piece
+ numbers of pieces that differ between the current values of $ZTOLDVAL and
+ $ZTVALUE. If the trigger specifies a piece separator, but does not specify
+ any pieces of interest, $ZTUPDATE identifies all changed pieces. $ZTUPDATE
+ is 0 in all other cases (that is: for SET commands where the GT.M trigger
+ does not specify a piece separator or for KILLs). Note that if an update
+ matches more than one trigger, all matching triggers see the same
+ $ZTOLDVAL at trigger entry but potentially different values of $ZTVALUE so
+ $ZTUPDATE could change due to the actions of each matching trigger even
+ though all matching triggers have identical -[z]delim and -piece
+ specifications.
+
+ Example:
+
+ +^trigvn -commands=Set -pieces=1;3:6 -delim="|" -xecute="Write !,$ZTUPDATE"
+
+ In the above trigger definition entry, $ZTUPDATE displays a comma
+ separated list of the changed piece numbers if on of the pieces of
+ interest: 1,3,4,5,or 6 are modified by the update.
+
+ GTM>write ^trigvn
+ Window|Table|Chair|Curtain|Cushion|Air Conditioner
+ GTM>set ^trigvn="Window|Dining Table|Chair|Vignette|Pillow|Air Conditioner"
+ 4,5
+
+ Note that even though piece numbers 2,4 and 5 are changed, $ZTUPDATE
+ displays only 4,5 because the trigger is not defined for updates for the
+ second piece.
+
+3 $ZTVAlue
+ $ZTVAlue
+
+ For SET, $ZTVALUE has the value assigned to the node by the explicit SET
+ operation. Modifying $ZTVALUE within a trigger modifies the eventual value
+ GT.M assigns to the node. Note that changing $ZTVALUE has a small
+ performance impact because it causes an additional update operation on the
+ node once all trigger code completes. If a node has multiple associated
+ triggers each trigger receives the current value of $ZTVALUE, however,
+ because the triggers run in arbitrary order, FIS strongly recommends no
+ more than one trigger change any given element of application data, for
+ example, a particular piece. For KILL and its variants, $ZTVALUE returns
+ the empty string. While GT.M accepts updates to $ZTVALUE within the
+ trigger code invoked for a KILL or any of its variants, it ultimately
+ discards any such value. Outside trigger context, attempting to SET
+ $ZTVALUE produces a SETINTRIGONLY error.
+
+3 $ZTWOrmhole
+ $ZTWOrmhole
+
+ $ZTWORMHOLE allows you to specify a string up to 128KB of information you
+ want to make available during trigger execution. You can use $ZTWORMHOLE
+ to supply an application-context or process context to your trigger logic.
+ Because GT.M makes $ZTWORMHOLE available throughout the duration of the
+ process, you can access or update $ZTWORMHOLE both from inside and outside
+ a trigger.
+
+ $ZTWORMHOLE provides a mechanism to access information from a
+ process/application context that is otherwise unavailable in trigger
+ context. GT.M records any non-empty string value of $ZTWORMHOLE in the
+ GT.M database journal file as part of any update that invokes at least one
+ trigger which references $ZTWORMHOLE. GT.M also transmits any non-NULL
+ $ZTWORMHOLE value in the replication stream, thus providing the same
+ context to triggers invoked by MUPIP processes (either as part of the
+ replicating instance update process or as part of MUPIP journal
+ recovery/rollback). Therefore, whenever you use $ZTWORMHOLE in a trigger,
+ you create something like a wormhole for process context that is otherwise
+ NEWed in the run-time or non-existent in MUPIP.
+
+ Note that if trigger code does not reference $ZTMORMHOLE, GT.M does not
+ make it available to MUPIP (via the journal files or replication stream).
+ Therefore, if a replicating secondary has different trigger code than the
+ initiating primary (an unusual configuration) and the triggers on the
+ replicating node require information from $ZTWORMHOLE, the triggers on the
+ initiating node must reference $ZTWORMHOLE to ensure GT.M maintains the
+ data it contains for use by the update process on the replicating node.
+ While you can change $ZTWORMHOLE within trigger code, because of the
+ arbitrary ordering of triggers on the same node, such an approach requires
+ careful design and implementation. GTM allows $ZTWORMHOLE to be NEW'd.
+ NEWing $ZTWORMHOLE is slightly different from NEWing other ISVs/variables
+ in the sense that the former retains its original value whereas the latter
+ does not. However, like other NEWs, GT.M restores $ZTWORMHOLE's value when
+ the stack level pops.
+
+ The following table summarizes the read/write permissions assigned to all
+ trigger-related ISVs within trigger context and outside trigger context.
+
+ +------------------------------------------------------------------------+
+ | Intrinsic Special | Within Trigger | Notes |
+ | Variable | Context | |
+ |-------------------+----------------+-----------------------------------|
+ | | | Set to gtm_trigger_etrap or the |
+ | $ETRAP | Read / Write | empty string when entering |
+ | | | trigger context. |
+ |-------------------+----------------+-----------------------------------|
+ | $REFERENCE | Read only | Restored at the completion of a |
+ | | | trigger. |
+ |-------------------+----------------+-----------------------------------|
+ | $TEST | Read only | Restored at the completion of a |
+ | | | trigger. |
+ |-------------------+----------------+-----------------------------------|
+ | | | Always >=1 in trigger code; must |
+ | $TLEVEL | Read only | be the same as the completion of |
+ | | | processing a trigger as it was at |
+ | | | the start. |
+ |-------------------+----------------+-----------------------------------|
+ | $ZTNAME | Read only | Returns the trigger name. |
+ |-------------------+----------------+-----------------------------------|
+ | $ZTDATA | Read only | Shows prior state. |
+ |-------------------+----------------+-----------------------------------|
+ | $ZTLEVEL | Read only | Shows trigger nesting. |
+ |-------------------+----------------+-----------------------------------|
+ | $ZTOLDVAL | Read only | Shows the pre-update value. |
+ |-------------------+----------------+-----------------------------------|
+ | $ZTRAP | Read only - "" | Must use $ETRAP in trigger code. |
+ |-------------------+----------------+-----------------------------------|
+ | $ZTRIGGEROP | Read only | Shows the triggering command. |
+ |-------------------+----------------+-----------------------------------|
+ | $ZTUPDATE | Read only | Lists modified pieces (if |
+ | | | requested) for SET. |
+ |-------------------+----------------+-----------------------------------|
+ | $ZTVALUE | Read / Write | Can change the eventual applied |
+ | | | value for SET. |
+ |-------------------+----------------+-----------------------------------|
+ | | | Holds application context because |
+ | $ZTWORMHOLE | Read / Write | trigger code has no access to the |
+ | | | local variable context. |
+ |-------------------+----------------+-----------------------------------|
+ | | | Holds outermost transaction |
+ | $ZTSLATE | Read/ Write | context for chained or nested |
+ | | | triggers. |
+ +------------------------------------------------------------------------+
+
+1 IO_Processing
+ IO Processing
+
+ This chapter describes the following topics which relate to input and
+ output processing:
+
+ * Input/Output Intrinsic Special Variables, and their Maintenance.
+
+ GT.M provides several intrinsic special variables that allow processes
+ to examine, and in some cases change, certain aspects of the
+ input/output (I/O) processing. The focus in this chapter is how GT.M
+ handles the standard ones, such as $IO, $X, $Y, and those that are
+ GT.M-specific (for example, $ZA, $ZB).
+
+ * Input/Output Devices
+
+ Each device type supported by GT.M responds to a particular subset of
+ deviceparameters, while ignoring others. Devices may be programmed in
+ a device-specific manner, or in a device-independent manner. This
+ chapter discusses each device type, and provides tables of their
+ deviceparameters.
+
+ * Input/Output Commands and their Deviceparameters
+
+ GT.M bases its I/O processing on a simple character stream model. GT.M
+ does not use any pre-declared formats. This chapter describes the GT.M
+ I/O commands OPEN, USE, READ, WRITE, and CLOSE.
+
+ OPEN, USE, and CLOSE commands accept deviceparameters, which are keywords
+ that permit a GT.M program to control the device state. Some
+ deviceparameters require arguments. The current ANSI standard for GT.M
+ does not define the deviceparameters for all devices. This chapter
+ includes descriptions of the GT.M deviceparameters in the sections
+ describing each command.
+
+2 Using_Terminals
+ Using Terminals
+
+ A GT.M process assigns $PRINCIPAL to the UNIX standard input of the
+ process (for READ) and standard output (for WRITE). For a local
+ interactive process, $PRINCIPAL identifies the "terminal" from which the
+ user is signed on.
+
+ While all terminals support the CTRAP deviceparameter, only $PRINCIPAL
+ supports CENABLE. While CTRAP allows terminal input to redirect program
+ flow, CENABLE allows the terminal user to invoke the Direct Mode.
+
+ Directly connected printers often appear to GT.M as a terminal (although
+ printers generally do not provide input) regardless of whether the printer
+ is connected to the computer with a high speed parallel interface, or an
+ asynchronous terminal controller.
+
+3 Set_Characteristics
+ Set Characteristics
+
+ GT.M does not isolate its handling of terminal characteristics from the
+ operating system environment at large. GT.M inherits the operating system
+ terminal characteristics in effect at the time the GT.M image is invoked.
+ When GT.M exits, the terminal characteristics known by the operating
+ system are restored.
+
+ However, if the process temporarily leaves the GT.M environment with a
+ ZSYSTEM command , GT.M does not recognize any changes to the terminal
+ characteristics left by the external environment. This may cause
+ disparities between the physical behavior of the terminal, and the
+ perceived behavior by GT.M.
+
+ UNIX enforces standard device security for explicit OPENs of terminals
+ other than the sign-in terminal ($PRINCIPAL). If you are unable to OPEN a
+ terminal, contact your system manager.
+
+ USE of a terminal causes the device driver to flush the output buffer.
+ This feature of the USE command provides routine control over the timing
+ of output, which is occasionally required. However, it also means that
+ redundant USE commands may induce an unnecessary performance penalty.
+ Therefore, FIS recommends restricting USE commands to redirecting I/O,
+ modifying deviceparameters, and initiating specifically required flushes.
+
+ The terminal input buffer size is fixed at 1024 on UNIX and a variable
+ read terminates after 1023 characters.
+
+4 Set_TERM
+ Set TERM
+
+ The environment variable $TERM must specify a terminfo entry that
+ accurately matches the terminal (or terminal emulator) settings. Refer to
+ the terminfo man pages for more information on the terminal settings of
+ the platform where GT.M needs to run.
+
+ Some terminfo entries may seem to work properly but fail to recognize
+ function key sequences or position the cursor properly in response to
+ escape sequences from GT.M. GT.M itself does not have any knowledge of
+ specific terminal control characteristics. Therefore, it is important to
+ specify the right terminfo entry to let GT.M communicate correctly with
+ the terminal. You may need to add new terminfo entries depending on their
+ specific platform and implementation. The terminal (emulator) vendor may
+ also be able to help.
+
+ GT.M uses the following terminfo capabilities. The full variable name is
+ followed by the capname in parenthesis:
+
+ auto_right_margin(am), clr_eos(ed), clr_eol(el), columns(cols), cursor_address(cup), cursor_down(cud1),cursor_left(cub1), cursor_right(cuf1), cursor_up(cuu1), eat_newline_glitch(xenl), key_backspace(kbs), key_dc(kdch1),key_down(kcud1), key_left(kcub1), key_right(kcuf1), key_up(kcuu1), key_insert(kich1), keypad_local(rmkx),keypad_xmit(smkx), lines(lines).
+
+ GT.M sends keypad_xmit before terminal reads for direct mode and READs
+ (other than READ *) if EDITING is enabled. GT.M sends keypad_local after
+ these terminal reads.
+
+3 Summary
+ Summary
+
+ The following tables provide a brief summary of deviceparameters for
+ terminals, grouped into related areas.
+
+ +----------------------------------------------------------------------+
+ | Error Processing Deviceparameters |
+ |----------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-----------------+---------+------------------------------------------|
+ | EXCEPTION=expr | O/U/C | Controls device-specific error handling. |
+ +----------------------------------------------------------------------+
+
+ +------------------------------------------------------------------------+
+ | Interaction Management Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-----------------------+---------+--------------------------------------|
+ | | | Controls whether <CTRL-C> on |
+ | [NO]CENABLE | U | $PRINCIPAL causes GT.M to go to |
+ | | | direct mode. |
+ |-----------------------+---------+--------------------------------------|
+ | CTRAP=expr | U | Controls vectoring on trapped <CTRL> |
+ | | | characters. |
+ |-----------------------+---------+--------------------------------------|
+ | [NO]ESCAPE | U | Controls escape sequence processing. |
+ |-----------------------+---------+--------------------------------------|
+ | | | Controls interpretation by the |
+ | [NO]PASTHRU | U | operating system of special control |
+ | | | characters (for example <CTRL-B>). |
+ |-----------------------+---------+--------------------------------------|
+ | [NO]TERMINATOR[=expr] | U | Controls characters that end a READ |
+ +------------------------------------------------------------------------+
+
+ +------------------------------------------------------------------+
+ | Flow Control Deviceparameters |
+ |------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-----------------+---------+--------------------------------------|
+ | [NO]CONVERT | U | Controls forcing input to uppercase. |
+ |-----------------+---------+--------------------------------------|
+ | [NO]FILTER | U | Controls some $X, $Y maintenance. |
+ |-----------------+---------+--------------------------------------|
+ | FLUSH | U | Clears the typeahead buffer. |
+ |-----------------+---------+--------------------------------------|
+ | [NO]HOSTSYNC | U | Controls host's use of XON/XOFF. |
+ |-----------------+---------+--------------------------------------|
+ | [NO]READSYNC | U | Controls wrapping READs in XON/XOFF. |
+ |-----------------+---------+--------------------------------------|
+ | [NO]TTSYNC | U | Controls input response to XON/XOFF. |
+ |-----------------+---------+--------------------------------------|
+ | [NO]TYPEAHEAD | U | Controls unsolicited input handling. |
+ +------------------------------------------------------------------+
+
+ +------------------------------------------------------------------------+
+ | Screen Management Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-------------------+---------+------------------------------------------|
+ | CLEARSCREEN | U | Clears from cursor to end-of-screen. |
+ |-------------------+---------+------------------------------------------|
+ | DOWNSCROLL | U | Moves display down one line. |
+ |-------------------+---------+------------------------------------------|
+ | [NO]ECHO | U | Controls the host echo of input. |
+ |-------------------+---------+------------------------------------------|
+ | ERASELINE | U | Clears from cursor to end-of-line. |
+ |-------------------+---------+------------------------------------------|
+ | [Z]LENGTH=intexpr | U | Controls maximum number of lines on a |
+ | | | page ($Y). |
+ |-------------------+---------+------------------------------------------|
+ | UPSCROLL | U | Moves display up one line. |
+ |-------------------+---------+------------------------------------------|
+ | [Z]WIDTH=intexpr | U | Controls the maximum width of an output |
+ | | | line ($X). |
+ |-------------------+---------+------------------------------------------|
+ | [Z][NO]WRAP | U | Controls handling of output lines longer |
+ | | | than the maximum width. |
+ |-------------------+---------+------------------------------------------|
+ | X=intexpr | U | Positions the cursor to column intexpr. |
+ |-------------------+---------+------------------------------------------|
+ | Y=intexpr | U | Positions the cursor to row intexpr. |
+ +------------------------------------------------------------------------+
+
+ O: Applies to the OPEN command
+
+ U: Applies to the USE command
+
+ C: Applies to the CLOSE command
+
+2 Sequential_Files
+ Sequential Files
+
+ GT.M provides access to sequential files. These files allow linear access
+ to records. Sequential files are used to create programs, store reports,
+ and to communicate with facilities outside of GT.M.
+
+3 Sequential_File_Pointers
+ Sequential File Pointers
+
+ Sequential file I/O operations use a construct called a file pointer. The
+ file pointer logically identifies the next record to read or write. OPEN
+ commands position the file pointer at the beginning of the file (REWIND)
+ or at the end-of-file (APPEND). APPEND cannot reposition a file currently
+ open. Because the position of each record depends on the previous record,
+ a WRITE destroys the ability to reliably position the file pointer to
+ subsequent records in a file. Therefore, by default (NOTRUNCATE), GT.M
+ permits WRITEs only when the file pointer is positioned at the end of the
+ file.
+
+ A file that has been previously created and contains data that should be
+ retained can also be opened with the device parameter APPEND.
+
+ If a device has TRUNCATE enabled, a WRITE issued when the file pointer is
+ not at the end of the file causes all contents after the current file
+ pointer to be discarded. This effectively moves the end of the file to the
+ current position and permits the WRITE.
+
+3 Line_Terminators
+ Line Terminators
+
+ LF ($CHAR(10)) terminates the logical record for all M mode sequential
+ files, TRM, PIPE, and FIFO. For non FIXED format sequential files and
+ terminal devices for which character set is not M, all the standard
+ Unicode line terminators terminate the logical record. These are U+000A
+ (LF), U+0000D (CR), U+000D followed by U+000A (CRLF), U+0085 (NEL), U+000C
+ (FF), U+2028 (LS) and U+2029 (PS).
+
+3 READ_/_WRITE_Operations
+ READ / WRITE Operations
+
+ The following table describes all READ and WRITE operations for STREAM,
+ VARIABLE, and FIXED format sequential files having automatic record
+ termination enabled (WRAP) or disabled (NOWRAP).
+
+ +------------------------------------------------------------------------+
+ | Command | WRAP or | STREAM or VARIABLE format file | FIXED format |
+ | | NOWRAP | behavior | file behavior |
+ |-----------+---------+---------------------------------+----------------|
+ | READ | | Write the entire argument, but | Similar to |
+ | format or | WRAP | anytime $X is about to exceed | VARIABLE but |
+ | WRITE or | | WIDTH: insert a <LF> character, | no <LF> |
+ | WRITE * | | set $X to 0, increment $Y | |
+ |-----------+---------+---------------------------------+----------------|
+ | | | Write up to WIDTH-$X (original | |
+ | | | $X) characters of the argument, | |
+ | | | update $X; | |
+ | | |---------------------------------| |
+ | | | | VARIABLE | |
+ | | | | ($X=WIDTH) : | |
+ | | | | Write up to | |
+ | | | STREAM | WIDTH-$X | |
+ | READ | | ($X=WIDTH) : | characters | |
+ | format or | | Write up to | unless WIDTH-$X | Same as |
+ | WRITE or | NOWRAP | WIDTH | equals 65535, | VARIABLE |
+ | WRITE * | | characters | in which case | |
+ | | | unless WIDTH | write all of | |
+ | | | equals 65535, | the argument. | |
+ | | | in which case | Write no more | |
+ | | | write all of | output to the | |
+ | | | the argument. | device until a | |
+ | | | | WRITE ! or a | |
+ | | | | SET $X makes $X | |
+ | | | | less than | |
+ | | | | WIDTH. | |
+ |-----------+---------+---------------------------------+----------------|
+ | | | | Write PAD |
+ | READ or | | Write <LF>, set $X to 0, | bytes to bring |
+ | WRITE ! | either | increment $Y | the current |
+ | | | | record to |
+ | | | | WIDTH |
+ |-----------+---------+---------------------------------+----------------|
+ | | | | Write PAD |
+ | | | | bytes to bring |
+ | | | | the current |
+ | WRITE # | either | Write <FF>,<LF>, set $X to 0, | record to |
+ | | | increment $Y | WIDTH, then a |
+ | | | | <FF> followed |
+ | | | | by WIDTH-1 PAD |
+ | | | | bytes |
+ |-----------+---------+---------------------------------+----------------|
+ | | | | After a WRITE, |
+ | | | | if $X >0, |
+ | | | | perform an |
+ | | | | implicit |
+ | | | | "WRITE !" |
+ | | | | adding PAD |
+ | | | | bytes to |
+ | CLOSE | either | After a WRITE, if $X > 0, Write | create a full |
+ | | | <LF> | record. If you |
+ | | | | need to avoid |
+ | | | | trailing PAD |
+ | | | | bytes set $X |
+ | | | | to 0 before |
+ | | | | closing a |
+ | | | | FIXED format |
+ | | | | file. |
+ |-----------+---------+---------------------------------+----------------|
+ | | | | Return WIDTH |
+ | | | Return characters up to | characters; no |
+ | | | $X=WIDTH, or until encountering | maintenance of |
+ | READ X | either | an <LF> or EOF. If <LF> | $X and $Y, |
+ | | | encountered, set $X to 0, | except that |
+ | | | increment $Y | EOF increments |
+ | | | | $Y |
+ |-----------+---------+---------------------------------+----------------|
+ | | | | Return |
+ | | | Return characters up to the | MIN(WIDTH, |
+ | | | first of $X=WIDTH or len | len) |
+ | READ | | characters, or encountering a | characters; no |
+ | X#len | either | <LF> or EOF; if up to len | maintenance of |
+ | | | characters or EOF update $X, | $X and $Y, |
+ | | | otherwise set $X to 0 and | except that |
+ | | | increment $Y | EOF increments |
+ | | | | $Y |
+ |-----------+---------+---------------------------------+----------------|
+ | | | | Return the |
+ | | | | code for one |
+ | | | Return the code for one | character, if |
+ | | | character and increment $X, if | EOF return -1; |
+ | READ *X | either | WIDTH=$X or <LF> encountered, | no maintenance |
+ | | | set $X=0, increment $Y; if EOF | of $X and $Y, |
+ | | | return -1 | except that |
+ | | | | EOF increments |
+ | | | | $Y |
+ +------------------------------------------------------------------------+
+
+ **Note**
+
+ o EOF == end-of-file; <FF>== ASCII form feed; <LF> == ASCII line feed;
+ o In M mode, and by default in UTF-8 mode PAD == <SP> == ASCII space.
+ o "READ format" in this table means READ ? or READ <strlit>
+ o A change to WIDTH implicitly sets WRAP unless NOWRAP follows in the
+ deviceparameter list
+ o In VARIABLE and STREAM mode, READ (except for READ *) never returns
+ <LF> characters
+ o In M mode, the last setting of RECORDSIZE or WIDTH for the device
+ determines WIDTH
+ o In UTF-8 mode, RECORDSIZE is in bytes and WIDTH is in characters and
+ the smaller acts as the WIDTH limit in the table.
+ o In UTF-8 mode, FIXED mode writes <SP> to the RECORDSIZE when the next
+ character won't fit.
+ o In UTF-8 mode, all READ forms do not return trailing PAD characters.
+ o In UTF-8 mode, all characters returned by all forms of FIXED mode READ
+ are from a single record.
+ o WRITE for a Sequential Disk (SD) device works at the current file
+ position, whether attained with APPEND, REWIND or SEEK.
+ o GT.M manages any BOM for UTF mode files by ensuring they are at the
+ beginning of the file and produces a BOMMISMATCH error for an attempt
+ to change the byte-ordering on OPEN for an existing file.
+ o An attempt to OPEN a non-zero length file WRITEONLY without either
+ NEWVERSION or TRUNCATE in UTF mode produces an OPENDEVFAIL due to the
+ fact that any existing BOM information cannot be verified.
+ o Note that with GT.M SD encryption, because of the state information
+ associated with encryption processing, encrypted files require the
+ file to be WRITEn or READ from the beginning rather than from an
+ arbitrary position.
+
+3 _Binary_Files
+ Binary Files
+
+ To write a binary data file, open it with FIXED:WRAP:CHSET="M" and set $X
+ to zero before the WRITE to avoid filling the last record with spaces (the
+ default PAD byte value).
+
+ **Note**
+
+ With CHSET not "M", FIXED has a different definition. Each record is
+ really the same number of bytes as specified by RECORDSIZE. Padding bytes
+ are added as needed to each record.
+
+ Example:
+
+ bincpy(inname,outname); GT.M routine to do a binary copy from file named in argument 1 to file named in argument 2
+ ;
+ new adj,nrec,rsize,x
+ new $etrap
+ set $ecode="",$etrap="goto error",$zstatus=""
+ set rsize=32767 ; max recordsize that keeps $X on track
+ open inname:(readonly:fixed:recordsize=rsize:exception="goto eof")
+ open outname:(newversion:stream:nowrap:chset="M")
+ for nrec=1:1 use inname read x use outname write x
+ eof
+ if $zstatus["IOEOF" do quit
+ . set $ecode=""
+ . close inname
+ . use outname
+ . set adj=$x
+ . set $x=0 close outname
+ . write !,"Copied ",$select((nrec-1)<adj:adj,1:((nrec-1)*rsize)+adj)," bytes from ",inname," to ",outname
+ else use $principal write !,"Error with file ",inname,":"
+ error
+ write !,$zstatus
+ close inname,outname
+ quit
+
+3 Summary
+ Summary
+
+ The following tables provide a brief summary of deviceparameters for
+ sequential files grouped into related areas.
+
+ +----------------------------------------------------------------------+
+ | Error Processing Deviceparameters |
+ |----------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-----------------+---------+------------------------------------------|
+ | EXCEPTION=expr | O/U/C | Controls device-specific error handling. |
+ +----------------------------------------------------------------------+
+
+ +------------------------------------------------------------------------+
+ | File Pointer Positioning Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-----------------+---------+--------------------------------------------|
+ | APPEND | O | Positions file pointer at EOF. |
+ |-----------------+---------+--------------------------------------------|
+ | REWIND | O/U/C | Positions file pointer at start of the |
+ | | | file. |
+ |-----------------+---------+--------------------------------------------|
+ | | | Positions the current file pointer to the |
+ | | | location specified in strexpr. The format |
+ | | | of strexpr is a string of the form |
+ | | | "[+|-]integer" where unsigned value |
+ | | | specifies an offset from the beginning of |
+ | | | the file, and an explicitly signed value |
+ | | | specifies an offset relative to the |
+ | SEEK=strexpr | O/U | current file position. For STREAM or |
+ | | | VARIABLE format, the positive intexpr |
+ | | | after any sign is a byte offset, while for |
+ | | | a FIXED format, it is a record offset. In |
+ | | | order to deal with the possible presence |
+ | | | of a Byte Order Marker (BOM), SEEK for a |
+ | | | FIXED format file written in a UTF |
+ | | | character set must follow at least one |
+ | | | prior READ since the device was created. |
+ +------------------------------------------------------------------------+
+
+ +------------------------------------------------------------------------+
+ | File Format Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETERS | COMMAND | COMMENT |
+ |--------------------+---------+-----------------------------------------|
+ | [NO]FIXED | O | Controls whether records have fixed |
+ | | | length. |
+ |--------------------+---------+-----------------------------------------|
+ | [Z]LENGTH=intexpr | U | Controls virtual page length. |
+ |--------------------+---------+-----------------------------------------|
+ | RECORDSIZE=intexpr | O | Specifies maximum record size. |
+ |--------------------+---------+-----------------------------------------|
+ | STREAM | O | Specifies the STREAM format. |
+ |--------------------+---------+-----------------------------------------|
+ | VARIABLE | O | Controls whether records have variable |
+ | | | length. |
+ |--------------------+---------+-----------------------------------------|
+ | [Z]WIDTH=intexpr | U | Controls maximum width of an output |
+ | | | line. |
+ |--------------------+---------+-----------------------------------------|
+ | [Z][NO]WRAP | O/U | Controls handling of records longer |
+ | | | than device width. |
+ +------------------------------------------------------------------------+
+
+ +------------------------------------------------------------------------+
+ | File Access Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-----------------+---------+--------------------------------------------|
+ | DELETE | C | Specifies file be deleted by CLOSE. |
+ |-----------------+---------+--------------------------------------------|
+ | GROUP=expr | O/C | Specifies file permissions for other users |
+ | | | in the owner's group. |
+ |-----------------+---------+--------------------------------------------|
+ | NEWVERSION | O | Specifies GT.M create a new version of |
+ | | | file. |
+ |-----------------+---------+--------------------------------------------|
+ | OWNER=expr | O/C | Specifies file permissions for the owner |
+ | | | of file. |
+ |-----------------+---------+--------------------------------------------|
+ | [NO]READONLY | O | Controls read-only file access. |
+ |-----------------+---------+--------------------------------------------|
+ | RENAME=expr | C | Specifies CLOSE replace name of a disk |
+ | | | file with name specified by expression. |
+ |-----------------+---------+--------------------------------------------|
+ | SYSTEM=expr | O/C | Specifies file permissions for the owner |
+ | | | of the file (same as OWNER). |
+ |-----------------+---------+--------------------------------------------|
+ | [NO]TRUNCATE | O/U | Controls overwriting of existing data in |
+ | | | file. |
+ |-----------------+---------+--------------------------------------------|
+ | UIC=expr | O/C | Specifies file's owner ID. |
+ |-----------------+---------+--------------------------------------------|
+ | WORLD=expr | O/C | Specifies file permissions for users not |
+ | | | in the owner's group. |
+ +------------------------------------------------------------------------+
+
+ O: Applies to the OPEN command
+
+ U: Applies to the USE command
+
+ C: Applies to the CLOSE command
+
+2 FIFO_Characteristics
+ FIFO Characteristics
+
+ FIFOs have most of the same characteristics as other sequential files,
+ except that READs and WRITEs can occur in any order.
+
+ The following characteristics of FIFO behavior may be helpful in using
+ them effectively.
+
+ With READ:
+
+ * If a READ is done while there is no data in the FIFO:
+
+ The process hangs until data is put into the FIFO by another process, or
+ the READ times out, when a timeout is specified.
+
+ The following table shows the result and the values of I/O status
+ variables for different types of READ operations on a FIFO device.
+
+ +------------------------------------------------------------------------+
+ | Operation | Result | $DEVICE | $ZA | $TEST | X | $ZEOF |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X:n | Normal | 0 | 0 | 1 | Data | 0 |
+ | | Termination | | | | Read | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X:n | Timeout with | 0 | 0 | 0 | empty | 0 |
+ | | no data read | | | | string | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | | Timeout with | | | | Partial | |
+ | READ X:n | partial data | 0 | 0 | 0 | data | 0 |
+ | | read | | | | | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | | | 1,Device | | | empty | |
+ | READ X:n | End of File | detected | 9 | 1 | string | 1 |
+ | | | EOF | | | | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X:0 | Normal | 0 | 0 | 1 | Data | 0 |
+ | | Termination | | | | Read | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X:0 | No data | 0 | 0 | 0 | empty | 0 |
+ | | available | | | | string | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | | Timeout with | | | | Partial | |
+ | READ X:0 | partial data | 0 | 0 | 0 | data | 0 |
+ | | read | | | | | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | | | 1,Device | | | empty | |
+ | READ X:0 | End of File | detected | 9 | 1 | string | 1 |
+ | | | EOF | | | | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X | Error | 1,<error | 9 | n/c | empty | 0 |
+ | | | signature> | | | string | |
+ +------------------------------------------------------------------------+
+
+ With WRITE:
+
+ * The FIFO device does non-blocking writes. If a process tries to WRITE
+ to a full FIFO and the WRITE would block, the device implicitly tries
+ to complete the operation up to a default of 10 times. If the
+ gtm_non_blocked_write_retries environment variable is defined, this
+ overrides the default number of retries. If the retries do not succeed
+ (remain blocked), the WRITE sets $DEVICE to "1,Resource temporarily
+ unavailable", $ZA to 9, and produces an error. If the GT.M process has
+ defined an EXCEPTION, $ETRAP or $ZTRAP, the error trap may choose to
+ retry the WRITE after some action or delay that might remove data from
+ the FIFO device.
+ * While it is hung, the process will not respond to <CTRL-C>.
+
+ With CLOSE:
+
+ * The FIFO is not deleted unless the DELETE qualifier is specified.
+ * If a process closes the FIFO with the DELETE qualifier, the FIFO
+ becomes unavailable to new users at that time.
+ * All processes currently USEing the FIFO may continue to use it, until
+ the last process attached to it CLOSES it, and is destroyed.
+ * Any process OPENing a FIFO with the same name as a deleted FIFO
+ creates a new one to which subsequent OPENs attach.
+
+ The default access permissions on a FIFO are the same as the mask settings
+ of the process that created the FIFO. Use the SYSTEM, GROUP, WORLD, and
+ UIC deviceparameters to specify FIFO access permissions. File permissions
+ have no affect on a process that already has the FIFO open.
+
+3 FIFO_Deviceparameter_Summary
+ FIFO Deviceparameter Summary
+
+ The following table summarizes the deviceparameters that can be used with
+ FIFOs.
+
+ +------------------------------------------------------------------------+
+ | File Format Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | CMD | DESCRIPTION |
+ |--------------------+-----+---------------------------------------------|
+ | [NO]FIXED | O | Controls whether records have fixed length. |
+ |--------------------+-----+---------------------------------------------|
+ | [Z]LENGTH=intexpr | U | Controls the virtual page length. |
+ |--------------------+-----+---------------------------------------------|
+ | RECORDSIZE=intexpr | O | Specifies the maximum record size. |
+ |--------------------+-----+---------------------------------------------|
+ | VARIABLE | O | Controls whether records have variable |
+ | | | length. |
+ |--------------------+-----+---------------------------------------------|
+ | [Z]WIDTH=intexpr | U | Sets the device's logical record size and |
+ | | | enables WRAP. |
+ |--------------------+-----+---------------------------------------------|
+ | [Z][NO]WRAP | O/U | Controls the handling of records longer |
+ | | | than the device width. |
+ +------------------------------------------------------------------------+
+
+ +------------------------------------------------------------------------+
+ | File Access Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | CMD | COMMENT |
+ |-----------------+-----+------------------------------------------------|
+ | | | Specifies that the FIFO should be deleted when |
+ | | | the last user closes it. If specified on an |
+ | | | OPEN, DELETE is activated only at the time of |
+ | DELETE | C | the close. No new attachements are allowed to |
+ | | | a deleted FIFO and any new attempt to use a |
+ | | | FIFO with the name of the deleted device |
+ | | | creates a new device. |
+ |-----------------+-----+------------------------------------------------|
+ | GROUP=expr | O/C | Specifies file permissions for other users in |
+ | | | owner's group. |
+ |-----------------+-----+------------------------------------------------|
+ | [NO]READONLY | O | OPENs a device for reading only (READONLY) or |
+ | | | reading and writing (NOREADONLY). |
+ |-----------------+-----+------------------------------------------------|
+ | OWNER=expr | O/C | Specifies file permissions for owner of file. |
+ |-----------------+-----+------------------------------------------------|
+ | | | Specifies that CLOSE replace the name of a |
+ | RENAME=expr | C | disk file with the name specified by the |
+ | | | expression. |
+ |-----------------+-----+------------------------------------------------|
+ | SYSTEM=expr | O/C | Specifies file permissions for owner of file |
+ | | | (same as OWNER). |
+ |-----------------+-----+------------------------------------------------|
+ | UIC=expr | O/C | Specifies the file's owner ID. |
+ |-----------------+-----+------------------------------------------------|
+ | WORLD=expr | O/C | Specifies file permissions for users not in |
+ | | | the owner's group. |
+ +------------------------------------------------------------------------+
+
+2 Using_Null_Devices
+ Using Null Devices
+
+ Null devices comprise of a collection of system purpose devices that
+ include /dev/null, /dev/zero, /dev/random, and /dev/urandom.
+
+ o /dev/null returns a null string on READ and sets $ZEOF
+ o /dev/random and /dev/urandom return a random value on READ and set
+ $ZEOF
+ o /dev/zero returns 0's on READ and does not set $ZEOF
+
+ A null device discards all output. GT.M maintains a virtual cursor
+ position for null devices as it does for terminals on output. Use null
+ devices for program testing and debugging, or for jobs that permit I/O to
+ be discarded under certain circumstances. For example, JOB processes must
+ have input and output devices associated with them, even though they do
+ not use them. Null devices are low overhead never-fail alternatives for
+ certain classes of I/O.
+
+3 Null_Deviceparameter_Summary
+ Null Deviceparameter Summary
+
+ +------------------------------------------------------------------------+
+ | Null Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |------------------------------------------------------------------------|
+ | O: Applies to the OPEN command |
+ | |
+ | U: Applies to the USE command |
+ | |
+ | C: Applies to the CLOSE command |
+ |------------------------------------------------------------------------|
+ | | | Controls device-specified error |
+ | | | handling. For the null device this is |
+ | EXCEPTION=expr | O/U/C | only EOF handling and therefore |
+ | | | exceptions can never be invoked except |
+ | | | by a READ. |
+ |-------------------+---------+------------------------------------------|
+ | [NO]FILTER[=expr] | U | Controls some $X,$Y maintenance. |
+ |-------------------+---------+------------------------------------------|
+ | [Z]LENGTH=intexpr | U | Controls the length of the virtual page. |
+ |-------------------+---------+------------------------------------------|
+ | [Z]WIDTH=intexpr | U | Controls maximum size of a record. |
+ |-------------------+---------+------------------------------------------|
+ | [Z][NO]WRAP | O/U | Controls handling of records longer than |
+ | | | the maximum width. |
+ |-------------------+---------+------------------------------------------|
+ | X=intexpr | U | Sets $X to intexpr. |
+ |-------------------+---------+------------------------------------------|
+ | Y=intexpr | U | Sets $Y to intexpr. |
+ +------------------------------------------------------------------------+
+
+3 Null_Device_Examples
+ Null Device Examples
+
+ This section contains examples of null device usage.
+
+ Example:
+
+ GTM>do ^runrep
+ runrep;
+ zprint ^runrep
+ set dev="/dev/null"
+ set hdr="********* REPORT HEADER ************"
+ open dev use dev
+ set x="" write hdr,!,$zdate($horolog),?30,$job,!
+ for set x=$order(^tmp($job,x)) quit:x="" do REPORT
+ quit
+ REPORT;
+ ;large amount of code
+ quit;
+
+ This program produces a report derived from the information in the global
+ variable ^tmp. The unspecified routine REPORT may potentially contain a
+ large amount of code. To see that the basic program functions without
+ error, the programmer may discard the output involved in favor of watching
+ the function. To run the program normally, the programmer simply has to
+ change the variable dev to name another device and the routine REPORT
+ writes to the dev device.
+
+ Example:
+
+ job ^X:(in="/dev/null":out="/dev/null":err="error.log")
+ JOB ^X:(IN="/dev/null":OUT="/dev/null":ERR="error.log")
+
+ This example issues a GT.M JOB command to execute the routine ^X in
+ another process. This routine processes a large number of global variables
+ and produces no output. In the example, the JOBbed process takes its input
+ from a null device, and sends its output to a null device. If the JOBbed
+ process encounters an error, it directs the error message to error.log.
+
+2 Using_PIPE_Devices
+ Using PIPE Devices
+
+ A PIPE device is used to access and manipulate the input and/or output of
+ a shell command as a GT.M I/O device. GT.M maintains I/O status variables
+ for a PIPE device just as it does for other devices. An OPEN of the device
+ starts a sub-process. Data written to the device by the M program is
+ available to the process on its STDIN. The M program can read the STDOUT
+ and STDERR of the sub-process. This facilitates output only applications,
+ such as printing directly from a GT.M program to an lp command; input only
+ applications, such as reading the output of a command such as ps; and
+ co-processing applications, such as using iconv to convert data from one
+ encoding to another.
+
+ A PIPE is akin to a FIFO device. Both FIFO and PIPE map GT.M devices to
+ UNIX pipes, the conceptual difference being that whereas a FIFO device
+ specifies a named pipe, but does not specify the process on the other end
+ of the pipe, a PIPE device specifies a process to communicate with, but
+ the pipes are unnamed. Specifically, an OPEN of a PIPE creates a
+ subprocess with which the GT.M process communicates.
+
+ A PIPE device is specified with a "PIPE" value for mnemonicspace on an
+ OPEN command.
+
+ **Note**
+
+ GT.M ignores the mnemonicspace specification on an OPEN of a previously
+ OPEN device and leaves the existing device with its original
+ characteristics.
+
+3 PIPE_Characteristics
+ PIPE Characteristics
+
+ The following characteristics of PIPE may be helpful in using them
+ effectively.
+
+ With Read:
+
+ A READ with no timeout reads whatever data is available to be read; if
+ there is no data to be read, the process hangs until some data becomes
+ available.
+
+ A READ with a timeout reads whatever data is available to be read, and
+ returns; if there is no data to be read, the process waits for a maximum
+ of the timeout period, an integer number of seconds, for data to become
+ available (if the timeout is zero, it returns immediately, whether or not
+ any data was read). If the READ returns before the timeout expires, it
+ sets $TEST to TRUE(1); if the timeout expires, it sets $TEST to FALSE (0).
+ When the READ command does not specify a timeout, it does not change
+ $TEST. READ specifying a maximum length (for example, READ X#10 for ten
+ characters) reads until either the PIPE has supplied the specified number
+ of characters, or a terminating delimiter.
+
+ The following table shows the result and values of I/O status variables
+ for various READ operations on a PIPE device.
+
+ +------------------------------------------------------------------------+
+ | Operation | Result | $DEVICE | $ZA | $TEST | X | $ZEOF |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X:n | Normal | 0 | 0 | 1 | Data | 0 |
+ | | Termination | | | | Read | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X:n | Timeout with | 0 | 0 | 0 | empty | 0 |
+ | | no data read | | | | string | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | | Timeout with | | | | Partial | |
+ | READ X:n | partial data | 0 | 0 | 0 | data | 0 |
+ | | read | | | | | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | | | 1,Device | | | empty | |
+ | READ X:n | End of File | detected | 9 | 1 | string | 1 |
+ | | | EOF | | | | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X:0 | Normal | 0 | 0 | 1 | Data | 0 |
+ | | Termination | | | | Read | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X:0 | No data | 0 | 0 | 0 | empty | 0 |
+ | | available | | | | string | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | | Timeout with | | | | Partial | |
+ | READ X:0 | partial data | 0 | 0 | 0 | data | 0 |
+ | | read | | | | | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | | | 1,Device | | | empty | |
+ | READ X:0 | End of File | detected | 9 | 1 | string | 1 |
+ | | | EOF | | | | |
+ |-----------+---------------+------------+-----+-------+---------+-------|
+ | READ X | Error | 1,<error | 9 | n/c | empty | 0 |
+ | | | signature> | | | string | |
+ +------------------------------------------------------------------------+
+
+ With WRITE:
+
+ The PIPE device does non-blocking writes. If a process tries to WRITE to a
+ full PIPE and the WRITE would block, the device implicitly tries to
+ complete the operation up to a default of 10 times. If the
+ gtm_non_blocked_write_retries environment variable is defined, this
+ overrides the default number of retries. If the retries do not succeed
+ (remain blocked), the WRITE sets $DEVICE to "1,Resource temporarily
+ unavailable", $ZA to 9, and produces an error. If the GT.M process has
+ defined an EXCEPTION, $ETRAP or $ZTRAP, the error trap may choose to retry
+ the WRITE after some action or delay that might remove data from the PIPE
+ device.
+
+ With WRITE /EOF:
+
+ WRITE /EOF to a PIPE device flushes, sets $X to zero (0) and terminates
+ output to the created process, but does not CLOSE the PIPE device. After a
+ WRITE /EOF, any additional WRITE to the device discards the content, but
+ READs continue to work as before. A WRITE /EOF signals the receiving
+ process to expect no further input, which may cause it to flush any output
+ it has buffered and terminate. You should explicitly CLOSE the PIPE device
+ after finishing all READs. If you do not want WRITE /EOF to flush any
+ pending output including padding in FIXED mode or a terminating EOL in
+ NOFIXED mode, SET $X=0 prior to the WRITE /EOF.
+
+ To avoid an indefinite hang doing a READ from a created process that
+ buffers its output to the input of the PIPE device, READ with timeout
+ (typically 0).
+
+ With CLOSE:
+
+ The CLOSE of a PIPE device prevents all subsequent access to the pipes
+ associated with the device. Unless the OPEN that created the device
+ specified INDEPENDENT, the process terminates. Note that any subsequent
+ attempt by the created process to read from its stdin (which would be a
+ closed pipe) returns an EOF and typical UNIX behavior would be to
+ terminate on such an event.
+
+3 PIPE_Device_Examples
+ PIPE Device Examples
+
+ The following examples show the use of deviceparameters and status
+ variables with PIPE devices.
+
+ Example:
+
+ pipe1;
+ set p1="test1"
+ open p1:(shell="/bin/sh":comm="cat")::"PIPE"
+ for i=1:1:10 do
+ . use p1
+ . write i,":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ",!
+ . read x
+ . use $P
+ . write x,!
+ close p1
+ quit
+
+ This WRITEs 10 lines of output to the cat command and reads the cat output
+ back into the local variable x. The GT.M process WRITEs each line READ
+ from the PIPE to the principal device. This example works because "cat" is
+ not a buffering command. The example above would not work for a command
+ such as tr that buffers its input.
+
+ Example :
+
+ pipe3;
+ set p1="test1"
+ open p1:(shell="/bin/sh":command="tr -d e")::"PIPE"
+ for i=1:1:1000 do
+ . use p1
+ . write i,":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ",!
+ . read x:0
+ . if '+$device use $principal write x,!
+ use p1
+ write /EOF
+ for read x quit:$zeof use $principal write x,! use p1
+ close p1
+ quit
+
+ This shows the use of tr (a buffering command) in the created process for
+ the PIPE device. To see the buffering effect the GT.M process WRITEs 1000
+ lines to the PIPE device. Different operating systems may have different
+ buffer sizes. Notice the use of the r x:0 and the check on $DEVICE in the
+ loop. If $DEVICE is 0, WRITE x writes the data read to the principal
+ device. No actual READs complete, however, until tr reaches its buffer
+ size and writes to its stdout. The final few lines remain buffered by tr
+ after the process finishes the first loop. The GT.M process then issues a
+ WRITE /EOF to the PIPE causing tr to flush its buffered lines. In the
+ final for loop the GT.M process uses the simple form of READ x from the
+ PIPE followed by a WRITE of each line to the principal device until $zeof
+ becomes TRUE.
+
+ Example :
+
+ pipe4;
+ set a="test"
+ open a:(command="nestin":independent)::"PIPE"
+ use a
+ set key=$KEY
+ write "Show ntestin still running after CLOSE of a",!
+ write "The parent process of 1 shows the parent shell has exited after CLOSE of a"
+ read line1,line2
+ use $principal
+ write !,line1,!,line2,!,!
+ set k="ps -ef | grep -v grep | grep -v sh | grep -w '"_key_"' | awk '{print $2}'"
+ set b="getpid"
+ open b:(command=k:readonly)::"PIPE"
+ use b
+ read pid
+ close a
+ close b
+ set k2="ps -ef | grep -v grep | grep -v sh | grep -w '"_pid_"'"
+ set c="psout"
+ open c:(command=k2:writeonly)::"PIPE"
+ close c
+ quit
+
+ This demonstrates that the created process nestin keeps running as an
+ INDEPENDENT process after the GT.M process CLOSEs the pipe. This GT.M
+ process uses another PIPE device to return the process id of ntestin and
+ READ it into pid so that it may be killed by this or another process,
+ should that be appropriate.
+
+ **Note**
+
+ "nestin.c" is a program which reads from standard input and writes to
+ standard output until it see and EOF. It then loops for 300 1sec sleeps
+ doing nothing. The purpose of using independent is as a server process
+ which continues until it receives some other signal for termination.
+
+ Example:
+
+ GTM>kill ^a
+
+ GTM>zprint ^indepserver
+ indepserver;
+ read x
+ write "received = ",x,!
+ set ^quit=0
+ for do quit:^quit
+ . if $data(^a) write "^a = ",^a,!
+ . Hang 5
+
+ GTM>set a="test"
+
+ GTM>open a:(command="mumps -run ^indepserver>indout":independent)::"pipe"
+
+ GTM>use a
+
+ GTM>write "instructions",!
+
+ GTM>close a
+
+ GTM>zsystem "cat indout"
+ received = instructions
+
+ GTM>set ^a=1
+
+ GTM>zsystem "cat indout"
+ received = instructions
+ ^a = 1
+ ^a = 1
+ ^a = 1
+
+ GTM>s ^quit=1
+
+ GTM>zsystem "cat indout"
+ received = instructions
+ ^a = 1
+ ^a = 1
+ ^a = 1
+ ^a = 1
+ GTM>
+
+ This is a simple example using a mumps process as a server.
+
+ Example:
+
+ pipe5;
+ set p1="test1"
+ set a=0
+ open p1:(shell="/bin/sh":command="cat":exception="goto cont1")::"PIPE"
+ set c=":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz"
+ for i=1:1:10000 do
+ . use p1
+ . write i_c,!
+ . use $principal write i,!
+ use p1
+ write /EOF
+ for read x quit:$zeof use $principal write x,! use p1
+ close p1
+ quit
+ cont1
+ if $zeof quit
+ if a=0 set a=i/2
+ set z=$za
+ ; use $device to make sure ztrap is caused by blocked write to pipe
+ set d=$device
+ if "1,Resource temporarily unavailable"=d DO
+ . use $p
+ . write "pipe full, i= ",i," $ZA = ",z,!
+ . set i=i-1
+ . use p1
+ . for j=1:1:a read x use $principal write j,"-",x,! use p1
+ quit
+
+ This demonstrates WRITEs to a PIPE device with blocking. The WRITE loop
+ has no READ to force the input pipe to fill up which blocks the cat
+ output, causing cat to stop reading its input, letting the pipe acting as
+ input on the PIPE device to fill up and creating the blocked condition.
+ When the process takes the $ZTRAP to cont1 it tests $DEVICE to determine
+ if the trap is caused by the full pipe. If so, it uses the for loop to
+ read half the number of lines output by the main loop. It decrements i and
+ returns to the original WRITE loop to retry the failed line and continue
+ with the WRITEs to the pipe. Depending upon the configuration of the
+ environment, it may trap several times before processing all lines.
+
+3 PIPE_Deviceparameter_Summary
+ PIPE Deviceparameter Summary
+
+ The following table summarizes the PIPE format deviceparameters.
+
+ +------------------------------------------------------------------------+
+ | DEVICE PARAMETER | CMD | DESCRIPTION |
+ |--------------------+-----+---------------------------------------------|
+ | [NO]FIXED | O | Controls whether records have fixed length |
+ |--------------------+-----+---------------------------------------------|
+ | RECORDSIZE=intexpr | O | Specifies the maximum record size. |
+ |--------------------+-----+---------------------------------------------|
+ | VARIABLE | O | Controls whether records have variable |
+ | | | length. |
+ |--------------------+-----+---------------------------------------------|
+ | [Z]WIDTH=intexpr | U | Sets the device's logical record size and |
+ | | | enables WRAP. |
+ |--------------------+-----+---------------------------------------------|
+ | [Z][NO]WRAP | O/U | Controls the handling of records longer |
+ | | | than the device width. |
+ +------------------------------------------------------------------------+
+
+ The following table summarizes PIPE access deviceparamters.
+
+ +------------------------------------------------------------------------+
+ | | | Specifies the command string to execut in a |
+ | | | created process for the PIPE device. GT.M uses |
+ | COMMAND=string | o | the default searching mechanism of the UNIX shell |
+ | | | for creating the process and initiating its |
+ | | | command(s). |
+ |----------------+---+---------------------------------------------------|
+ | SHELL=string | o | Specifies the path to a shell to be used instead |
+ | | | of the default shell |
+ |----------------+---+---------------------------------------------------|
+ | | | Specifies a device handle for a return pipe to |
+ | | | which the created process writes any standard |
+ | STDERR=string | o | error output. The GT.M process can USE, READ, and |
+ | | | CLOSE it, but cannot WRITE to it. When the GT.M |
+ | | | process CLOSEs the PIPE device the PIPE device |
+ | | | CLOSEs STDERR, if still OPEN. |
+ |----------------+---+---------------------------------------------------|
+ | WRITEONLY | o | Specifies that the GT.M process may only WRITE to |
+ | | | the created process via the PIPE device. |
+ |----------------+---+---------------------------------------------------|
+ | | | Specifies that the GT.M process may only READ |
+ | | | from the created process via the PIPE device. |
+ | READONLY | o | Output from both the standard output and the |
+ | | | standard error output of the created process is |
+ | | | available unless STDERR is specified. |
+ |----------------+---+---------------------------------------------------|
+ | PARSE | o | Specifies that GT.M parse the COMMAND and issue |
+ | | | an OPEN exception for any invalid command. |
+ |----------------+---+---------------------------------------------------|
+ | INDEPENDENT | o | Specifies that the created process continues to |
+ | | | execute after the PIPE device is CLOSEd. |
+ +------------------------------------------------------------------------+
+
+2 Using_Socket_Devices
+ Using Socket Devices
+
+ SOCKET devices are used to access and manipulate sockets. A SOCKET device
+ can have unlimited associated sockets. The default limit is 64. Set the
+ environment variable gtm_max_sockets to the number of maximum associated
+ sockets sockets that you wish to set for a GT.M process.
+ $VIEW("MAX_SOCKETS") returns the current value of the maximum number of
+ associated sockets.
+
+ At any time, only one socket from the collection can be the current
+ socket. If there is no current socket, an attempt to READ from, or WRITE
+ to the device, generates an error.
+
+ Sockets can be attached and detached from the collection of sockets
+ associated with a device. Detached sockets belong to a pseudo-device
+ called the "socketpool". A process can detach a socket from a device and
+ later attach it to the same device or another device.
+
+ **Caution**
- $ export gtmcompile="-LIST -LENGTH=56 -SPACE=2"
- $ gtm
- GTM>WRITE $ZCOMPILE
- -LIST -LENGTH=56 -SPACE=2
- GTM>SET $ZCOMPILE="-LIST -NOIGNORE"
- GTM>WRITE $ZCOMPILE
- -LIST -NOIGNORE
- GTM>ZLINK "A.m"
- GTM>HALT
- $ echo $gtmcompile
- -LIST -LENGTH=56 -SPACE=2
+ Currently, GT.M does not produce an error if a socket is attached to a
+ device having a different CHSET.
- This example uses the environment variable gtmcompile to set up $ZCOMPILE.
- Then it modifies $ZCOMPILE with the SET command. The ZLINK argument
- specifies a file with a .m extension (type), which forces a compile. The
- compile produces a listing for routine A.m and does not produce an object
- module if A.m contains compilation errors. After GT.M terminates, the
- shell command echo $gtmcompile demonstrates that the SET command did not
- change the environment variable.
+ **Note**
-2 $ZCstatus
- $ZCstatus
+ The GT.M socket device interface does not have the ability to pass sockets
+ between related or unrelated processes. Currently error trapping operates
+ on a device, rather than on a socket.
- $ZC[STATUS] holds the value of the status code for the last compilation
- performed by a ZCOMPILE command.
+3 Message_Management
+ Message Management
- GT.M does not permit the SET command to modify $ZSTATUS.
+ From an application perspective, the transport layers used by a socket
+ device are stream-oriented, with no provisions for implicit application
+ messages. Therefore, the following are two common protocols used to
+ segment application messages.
-2 $ZDAteform
- $ZDAteform
+ 1. One method is to use a, typically small, fixed length message
+ containing the length of the next, variable length, message. In GT.M a
+ simplistic writer might be:
- $ZDA[TEFORM] contains an integer value, specifying the output year format
- of $ZDATE(). $ZDATEFORM can be modified using the SET command. GT.M
- initializes $ZDATEFORM to the translation of the environment variable
- gtm_zdate_form. If gtm_zdate_form is not defined, GT.M initializes
- $ZDATEFORM to zero (0).
+ Write $Justify($Length(x),4),x
- Refer to "Functions" and "Utility Routines" chapters in the GT.M
- Programmer's Guide for more details.
+ A corresponding simplistic reader might be:
- Example:
+ read len#4,x#len
- GTM>WRITE $ZDATEFROM
- 0
- GTM>WRITE $ZDATE($H)
- 11/15/02
- GTM>SET $ZDATEFORM=1
- GTM>WRITE $ZDATE($H)
- 11/15/2002
+ The advantage of this approach is that the message content (the value
+ of x in the code fragments above) can contain any character. The
+ disadvantage is that detecting that the protocol has become
+ desynchronized is a problem.
-2 $ZDirectory
- $ZDirectory
+ 2. The other common method is to place a delimiter between each
+ application message. The protocol breaks if a message ever includes a
+ delimiter as part of its content.
- $ZD[IRECTORY] contains the string value of the full path of the current
- directory. Initially $ZDIRECTORY contains the default/current directory
- from which the GT.M image/process was activated.
+ The SOCKET device provides a facility for recognizing delimiters because
+ parsing messages for delimiters is cumbersome.
- If the current directory does not exist at the time of GT.M process
- activation, GT.M errors out.
+3 Socket_Read_Operation
+ Socket Read Operation
- Example:
+ TCP/IP is a stream-based protocol that guarantees that bytes arrive in the
+ order in which they were sent. However, it does not guarantee that they
+ will be grouped in the same packets.
- GTM>WRITE $ZDIR
- /usr/tmp
- GTM>SET $ZDIR=".."
- GTM>WRITE $ZDIR
- /usr
+ If packets arrive infrequently, or at varying rates that are sometimes
+ slow, a short interval can waste CPU cycles checking for an unlikely
+ event. On the other hand, if the handling of packets is time critical, a
+ long interval can introduce an undesirable latency. If packets arrive in a
+ rapid and constant flow (an unusual situation), the interval doesn't
+ matter as much, as there is always something in the buffer for the READ to
+ work with. If you do not specify MOREREADTIME, SOCKET READ implements a
+ dynamic approach of using a longer first interval of 200 ms when it finds
+ no data, then shortening the interval to 10 ms when data starts to arrive.
+ If you specify an interval, the SOCKET device always uses the specified
+ interval and does not adjust dynamically.
- This example displays the current working directory and changes $ZDIR to
- the parent directory.
+ Most SOCKET READ operations terminate as a result of the first condition
+ detected from (a) receipt of delimiters, (b) receipt of the maximum number
+ of characters, or (c) expiration of a timeout. Note that all of these
+ conditions are optional, and a specific READ may specify zero or more of
+ them. This section refers to these three conditions as "defined
+ terminating conditions". If a SOCKET READ is not subject to any of the
+ defined terminating conditions, it terminates after it has received at
+ least one character followed by an interval with no new characters. An
+ error can also terminate a READ. While none of the terminating conditions
+ is satisfied, the READ continues.
- $ZDIRECTORY is a read-write Intrinsic Special Variable, that is, it can
- appear on the left side of the equal sign (=) in the argument to a SET
- command. If an attempt is made to set $ZDIRECTORY to a non-existent
- directory specification, GT.M issues an error and keeps the value of
- $ZDIRECTORY unchanged.
+ The following flowchart represents the logic of a SOCKET READ.
- At image exit, GT.M restores the current directory to the directory that
- was the current directory when GT.M was invoked even if that directory
- does not exist.
+3 Socket_Read_Termination_Conditions
+ Socket Read Termination Conditions
-2 $ZEDit
- $ZEDit
+ A SOCKET READ operation terminates if any of the following conditions are
+ met:
- $ZED[IT] holds the value of the status code for the last edit session
- invoked by a ZEDIT command.
+ +------------------------------------------------------------------------+
+ | Terminating | Argument Contains | $Device | $Key | $Test |
+ | Conditions | | | | |
+ |----------------+-------------------------+---------+-----------+-------|
+ | Error | Empty String | Error | Empty | 1 |
+ | | | String | String | |
+ |----------------+-------------------------+---------+-----------+-------|
+ | Timeout* | Data received before | Empty | Empty | 0 |
+ | | timeout | String | String | |
+ |----------------+-------------------------+---------+-----------+-------|
+ | Delimiter* | Data up to, but not | Empty | Delimiter | 1 |
+ | | including the delimiter | String | String | |
+ |----------------+-------------------------+---------+-----------+-------|
+ | Fixed Length | String of Fixed Length | Empty | Empty | 1 |
+ | Met* | | String | String | |
+ |----------------+-------------------------+---------+-----------+-------|
+ | Width | Full width String | Empty | Empty | 1 |
+ | | | String | String | |
+ |----------------+-------------------------+---------+-----------+-------|
+ | | One (1) to as many | | | |
+ | | characters as provided | | | |
+ | | by the transport | | | |
+ | | interface before | | | |
+ | | waiting for an interval | | | |
+ | | (in milliseconds) | | | |
+ | | specified by | | | |
+ | | MOREREADTIME with no | | | |
+ | | additional input. If | | | |
+ | | MOREREADTIME is not | | | |
+ | | specified, buffer is | | | |
+ | Buffer Emptied | checked every 200 | Empty | Empty | 1 |
+ | | milliseconds for its | String | String | |
+ | | first input and then | | | |
+ | | every 10 milliseconds | | | |
+ | | until no new input | | | |
+ | | arrives and no other | | | |
+ | | terminating conditions | | | |
+ | | are met. | | | |
+ | | | | | |
+ | | IF MOREREADTIME is | | | |
+ | | specified, READ uses | | | |
+ | | that value exclusively | | | |
+ | | for buffer checks. | | | |
+ +------------------------------------------------------------------------+
- GT.M does not permit the SET or NEW command to modify $ZEDIT.
+ * denotes Defined Terminating Conditions
-2 $ZEOf
- $ZEOf
+ A non-fixed-length read, with no timeout and no delimiters (the sixth row
+ in the above table) requires a complex implementation of sequence of READs
+ to ensure a predictable result. This is because the transport layer stream
+ fragments delivered to the reader has only accidental correspondence with
+ the operations performed by the writer. For example, the following:
- $ZEO[F] contains a truth-valued expression indicating whether the last
- READ operation reached the end-of-file. $ZEOF equals TRUE (1) at EOF and
- FALSE (0) at other positions.
+ Write "Message 1","Message 2" is presented to the reader as the stream
+ "Message1Message2" but it can take from one (1) to 18 READ commands to
+ retrieve the entire stream.
- GT.M does not maintain $ZEOF for terminal devices.
+ Messaging protocol should implement READ in any of the following ways:
- $ZEOF refers to the end-of-file status of the current device. Therefore,
- exercise care in sequencing USE commands and references to $ZEOF.
+ 1. Use a delimiter to separate messages (generic READ and possibly a
+ larger value for MOREREADTIME).
+ 2. Specify messages as <length, value> pairs (a pair of fixed-length
+ READs (READ # ) and possibly a larger value for MOREREADTIME).
+ 3. Parse the bytes or characters as they come in (possibly a smaller
+ value for MOREADTIME)
- GT.M does not permit the SET or NEW command to modify $ZEOF.
+3 Read_Command
+ Read Command
- For more information on $ZEOF, refer to the "Input/Output Processing"
- chapter.
+ The READ command may be used to obtain data from a socket. A READ
+ operation terminates if any of the following are detected, in the order
+ specified below:
-2 $ZError
- $ZError
+ +------------------------------------------------------------------------+
+ | Terminating | Argument Contains | $Device | $Key |
+ | Condition | | | (Continued) |
+ |------------------+----------------------------+---------+--------------|
+ | Error | Empty string | Error | Empty string |
+ | | | string | |
+ |------------------+----------------------------+---------+--------------|
+ | Timeout | Data received before | Empty | Empty string |
+ | | timeout | string | |
+ |------------------+----------------------------+---------+--------------|
+ | Delimiter | Data up to, but not | Empty | Delimiter |
+ | | including the delimiter | string | string |
+ |------------------+----------------------------+---------+--------------|
+ | Fixed length met | String of fixed length | Empty | Empty string |
+ | | | string | |
+ |------------------+----------------------------+---------+--------------|
+ | | One (1) to as many | | |
+ | Buffer emptied | characters as happen to be | Empty | Empty string |
+ | | provided by the transport | string | |
+ | | interface | | |
+ +------------------------------------------------------------------------+
- $ZE[RROR] is supposed to hold the application-specific error-code
- corresponding to the GT.M error-code stored in $ECODE/$ZSTATUS.
+ A non-fixed-length read, with no timeout and no delimiters requires a
+ complex implementation of sequence of READs to ensure a predictable
+ result. This is because the transport layer stream fragments delivered to
+ the reader has only accidental correspondence with the operations
+ performed by the writer. For example, the following
- $ZERROR contains a default value of "Unprocessed $ZERROR, see $ZSTATUS" at
- process startup.
+ Write "Message 1","Message 2"
- $ZERROR can be SET but not NEWed.
+ is presented to the reader as the stream "Message1Message2" but it can
+ take from one (1) to 18 READ commands to retrieve the entire stream.
- The mapping of a GT.M error-code to the application-specific error-code is
- achieved as follows. Whenever GT.M encounters an error, $ECODE/$ZSTATUS
- gets set first. It then invokes the code that $ZYERROR points to if it is
- not null. It is intended that the code invoked by $ZYERROR use the value
- of $ZSTATUS to select or construct a value to which it SETs $ZERROR. If an
- error is encountered by the attempt to execute the code specified in
- $ZYERROR, GT.M sets $ZERROR to the error status encountered. If $ZYERROR
- is null, GT.M does not change the value of $ZERROR. In all cases, GT.M
- proceeds to return control to the code specified by $ZTRAP/$ETRAP or
- device EXCEPTION whichever is applicable.
+3 WRITE_Command
+ WRITE Command
-2 $ZGbldir
- $ZGbldir
+ The WRITE command sends data to a socket.
+
+ The WRITE command for SOCKET devices accepts the following
+ controlmnemonics:
- $ZG[BLDIR] contains the value of the current Global Directory filename.
- When $ZGBLDIR specifies an invalid or inaccessible file, GT.M cannot
- successfully perform database operations.
+ /L[ISTEN][(numexpr)]
- GT.M initializes $ZGBLDIR to the translation of the environment variable
- gtmgbldir. The value of the gtmgbldir environment variable may include a
- reference to another environment variable. If gtmgbldir is not defined,
- GT.M initializes $ZGBLDIR to null. When $ZGBLDIR is null, GT.M constructs
- a file name for the Global Directory using the name $gtmgbldir and the
- extension .gld in the current working directory.
+ where numexpr is in the range 1-5 and specifies the listen queue depth for
+ a listening socket. By default, an OPEN or USE with LISTEN immediately
+ sets the listen queue size to 1.
- $ZGBLDIR is a read-write Intrinsic Special Variable, (i.e., it can appear
- on the left side of the equal sign (=) in the argument to the SET
- command). SET $ZGBLDIR="" causes GT.M to assign $ZGBLDIR to the
- translation of gtmgbldir if that environment variable is defined. If it is
- not defined, then SET $ZGBLDIR="" causes GT.M to construct a file name
- using the name $gtmgbldir.gld in the current directory. GT.M permits
- $ZGBLDIR to be NEW'd. A $ZGBLDIR value may include an environment
- variable.
+ /W[AIT][(timeout)]
- SETting $ZGBLDIR also causes GT.M to attempt to open the specified file.
- If the file name is invalid or the file is inaccessible, GT.M triggers an
- error without changing the value of $ZGBLDIR.
+ where timeout is a "numexpr" that specifies how long in seconds a server
+ waits for a connection or data to become available on one of the sockets
+ in the current Socket Device.
- To establish a value for $ZGBLDIR outside of M, use the appropriate shell
- command to assign a translation to gtmgbldir. Defining gtmgbldir provides
- a convenient way to use the same Global Directory during a session where
- you repeatedly invoke and leave GT.M.
+ "WRITE !" inserts the character(s) of the first I/O delimiter (if any) to
+ the sending buffer. If "ZFF=expr" has been specified, "WRITE #" inserts
+ the characters of expr . Otherwise WRITE # has no effect. WRITE ! and
+ WRITE # always maintain $X and $Y in a fashion that emulates a terminal
+ cursor position except when the device is OPENed with a UTF CHSET because
+ the units for $X and $Y for terminals are in display columns while for
+ sockets they are in codepoints.
+
+ WRITE /PASS([targetpid],[timeout],handle[,handle]...)
+
+ WRIE /PASS allows a GT.M process to send DETACHed TCP or LOCAL sockets
+ (that is, sockets in the socket pool) to another GT.M process. The
+ receiving process should execute WRITE /ACCEPT to receive the socket.
+ WRITE /PASS and WRITE /ACCEPT require a current $IO that is a CONNECTed
+ (notLISTENing), LOCAL domain (not TCP), SOCKET device. GT.M issues
+ CONNSOCKREQ or LOCALSOCKREQ errors, respectively, when those conditions
+ are not met.
+
+ o If a numeric targetpid is specified, GT.M matches the value against
+ the process id ($JOB) of the process receiving the sockets. GT.M uses
+ a system service to perform this check on platforms that support it -
+ currently: Linux, AIX, and Solaris. On platforms which do not
+ implement the service (HP-UX), GT.M ignores the targetpid. If the pids
+ do not match, GT.M issues a PEERPIDMISMATCH error and does not
+ transfer the sockets.
+ o If a numeric timeout is specified, GT.M sets $TEST to 1 if the
+ transfer completes within the specified time, and otherwise sets $TEST
+ to 0 and does not transfer any of the sockets.
+ o Each handle specifies the name of a socket in the socket pool.
+ o On a successful transfer, GT.M closes the connection of the sending
+ process to the specified and sent sockets. In any case where the
+ transfer does not complete, GT.M retains all the sockets in the socket
+ pool of the sender.
+
+ WRITE /ACCEPT(.lvar,[sourcepid],[timeout][,[handle]]...)
+
+ WRITE /ACCEPT allows a GT.M process to receive a DETACHed TCP or LOCAL
+ sockets (that is, sockets in the socket pool) from another GT.M process .
+ The sending process should execute WRITE /PASS to send the socket. WRITE
+ /PASS and WRITE /ACCEPT require a current $IO that is a CONNECTed
+ (notLISTENing), LOCAL domain (not TCP), SOCKET device. GT.M issues
+ CONNSOCKREQ or LOCALSOCKREQ errors, respectively, when those conditions
+ are not met.
+
+ o lvar is an unsubscripted local variable name (lvn) which must be
+ passed by reference indicated with a period (".") prefix. On
+ successful completion, the specified unsubscripted lvn contains the
+ handles of the received socket, in the order they were sent, delimited
+ with a vertical bar ("|"). GT.M places the sockets in the socket pool,
+ so the process can ATTACH them to an appropriate SOCKET device for
+ subsequent use.
+ o If a numeric sourcepid is specified, GT.M matches the value against
+ the process id ($JOB) of the process sending the sockets. On platforms
+ which do not implement the service (HP-UX), GT.M ignores the
+ targetpid. If the pids do not match, GT.M issues a PEERPIDMISMATCH
+ error and does not transfer the sockets.
+ o If a numeric timeout is specified, GT.M sets $TEST to 1 if the
+ transfer completes within the specified time, and otherwise sets $TEST
+ to 0 and does not transfer the sockets.
+ o If any handles are specified, GT.M assigns the provided handle names
+ to the received sockets in the order in which they appear in the WRITE
+ /PASS of the sending process; empty items in the comma delimited
+ handle list act to preserve ordering. Where the list provides no
+ handle, the socket retains the handle provided by the sender. In
+ either case, if there is already a socket with the transfer handle
+ name in the socket pool, GT.M generates a new handle name for the
+ transfer socket. GT.M ignores excess handles specified beyond the
+ number of incoming sockets.
+
+ For both WRITE /PASS and WRITE /ACCEPT, $IO must be a SOCKET device, and
+ the current socket of the device must be CONNECTED(not LISTENING) and
+ LOCAL domain (not TCP).
+
+ SOCKET devices so not support mixing other READs and WRITEs with socket
+ passing on the same CONNECTED LOCAL socket and produce SOCKPASSDATAMIX
+ errors. The application may perform multiple WRITE /PASS and WRITE /ACCEPT
+ operations in either direction on the socket before issuing a CLOSE.
+
+ Note that the receiving process must establish desired deviceparameters
+ (e.g., DELIMITER) either by ATTACHing it to a SOCKET device that provides
+ the characteristic for all its sockets, or by a subsequent USE that
+ specifies the appropriate deviceparameter(s). GT.M transfers only the
+ socket connection itself, the socket handle, and buffered socket data (if
+ any).
- Changes to the value of $ZGBLDIR during a GT.M invocation only last for
- the current invocation and do not change the value of gtmgbldir.
+3 Socket_Device_Operation
+ Socket Device Operation
- Example:
+ Each socket may be in one of the following states (observable through
+ $KEY):
- $ gtmgbldir=test.gld
- $ export gtmgbldir
- $ gtm
- GTM>WRITE $zgbldir
- /usr/dev/test.gld
- GTM>SET $zgbldir="mumps.gld"
- GTM>WRITE $zgbldir
- mumps.gld
- GTM>HALT
- $ echo $gtmgbldir
- test.gld
+ * CREATEindicates that the socket exists.
+ * ESTABLISHEDAfter a successful OPEN or USE with the CONNECT device
+ parameter or when GT.M was started with a socket as the $PRINCIPAL
+ device.
+ * LISTENINGindicates that the OPEN or USE with the LISTEN
+ deviceparameter was successful and a listen queue was established.
- This example defines the environment variable gtmgbldir. Upon entering
- GT.M Direct Mode, $ZGBLDIR has the value supplied by gtmgbldir. The SET
- command changes the value. After the GT.M image terminates, the echo
- command demonstrates that gtmgbldir was not modified by the M SET command.
+ A listening socket used for accepting new connections goes through these
+ three states in one step with a single OPEN or USE. When a server does a
+ WRITE /WAIT, a client can establish a connection which creates a new
+ server socket. $KEY includes information about this new socket in the form
+ of CONNECT|handle|<address> where <address> is the IP address for TCP
+ sockets and path for LOCAL sockets.
- $ ls test.gld
- test.gld not found
- $ gtm
- GTM>WRITE $zgbldir
- /usr/dev/mumps.gld
- GTM>set $zgbldir="test.gld"
- %GTM-E-ZGBLDIRACC, Cannot access global directory
- "/usr/dev/test.gld". Retaining /usr/dev/mumps.gld"
- %SYSTEM-E-ENO2, No such file or directory
- GTM>WRITE $zgbldir
- /usr/dev/mumps.gld
- GTM>halt
- $
+ Each socket may have one or more sockets waiting for either an incoming
+ connection or data available to READ (observable through $ZKEY). $ZKEY
+ contains semi-colon (";") separated list of entries detailing any waiting
+ sockets for a current SOCKET device.
- The SET command attempts to change the value of $ZGBLDIR to test.gld.
- Because the file does not exist, GT.M reports an error and does not change
- the value of $ZGBLDIR.
+ For more information on $KEY and $ZKEY, refer to Chapter 8: "ISV".
- **Caution**
+3 Socket_Deviceparameter_Summary
+ Socket Deviceparameter Summary
- Attempting to restore an inaccessible initial Global Directory that has
- been NEW'd, can cause an error.
+ +------------------------------------------------------------------------+
+ | Error Processing Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-----------------+---------+--------------------------------------------|
+ | EXCEPTION=expr | O/U/C | Controls device-specific error handling. |
+ |-----------------+---------+--------------------------------------------|
+ | | | If $LENGTH(expr) and ("Tt"[$EXTRACT(expr)) |
+ | IOERROR=expr | O/U | then Error Trapping is enabled; otherwise |
+ | | | the application must check $DEVICE for |
+ | | | errors. |
+ +------------------------------------------------------------------------+
- Note
+ +------------------------------------------------------------------------+
+ | Format Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |--------------------+---------+-----------------------------------------|
+ | [NO]DELIMITER=expr | O/U | Specifies socket delimiter(s). |
+ |--------------------+---------+-----------------------------------------|
+ | [NO]FILTER=expr | U | Specifies character filtering for |
+ | | | socket output. |
+ |--------------------+---------+-----------------------------------------|
+ | LENGTH=expr, or | | Sets virtual page length for socket |
+ | | U | device. |
+ | ZLENGTH=expr | | |
+ |--------------------+---------+-----------------------------------------|
+ | ICHSET=expr | O/U/C | Specifies input character set |
+ |--------------------+---------+-----------------------------------------|
+ | OCHSET=expr | O/U/C | Specifies output character set |
+ |--------------------+---------+-----------------------------------------|
+ | [Z][NO]WRAP | O/U | Controls handling of records longer |
+ | | | than the device width. |
+ |--------------------+---------+-----------------------------------------|
+ | [Z]WIDTH=expr | U | Controls the maximum length of an |
+ | | | output message. |
+ |--------------------+---------+-----------------------------------------|
+ | Z[NO]FF=expr | O/U | Controls whether and what characters to |
+ | | | send in response to a WRITE #. |
+ +------------------------------------------------------------------------+
- Attempting to restore an inaccessible initial Global Directory that has
- been NEW'd, can cause an error.
+ +------------------------------------------------------------------------+
+ | Socket Establishment/Disconnect Deviceparameters |
+ |------------------------------------------------------------------------|
+ | DEVICEPARAMETER | COMMAND | COMMENT |
+ |-----------------+---------+--------------------------------------------|
+ | CONNECT=expr | O/U | expr specifies protocol, and protocol |
+ | | | specific information |
+ |-----------------+---------+--------------------------------------------|
+ | LISTEN=expr | O/U | Similar to CONNECT but binds the socket |
+ | | | for subsequent /LISTEN and /WAIT |
+ +------------------------------------------------------------------------+
-2 $ZINTerrupt
- $ZINTerrupt
+3 Socket_Device_Examples
+ Socket Device Examples
- $ZINT[ERRUPT] specifies the code to be XECUTE'd when an interrupt (for
- example, through a MUPIP INTRPT) is processed. While a $ZINTERRUPT action
- is in process, any additional interrupt signals are discarded. When an
- interrupt handler is invoked, the current values of $REFERENCE is saved
- and restored when the interrupt handler returns. The current device ($IO)
- is neither saved nor restored.
+ sockexamplemulti3.m demonstrates a use of $KEY and $ZKEY in a basic socket
+ I/O setup. It launches two jobs: a server process which opens a listening
+ socket and a client process which makes five connections to the server.
+ The server sends a message to each connection socket. Even-numbered client
+ sockets read the message partially but do not send a response back to the
+ server. Odd-numbered client sockets receive the full message and respond
+ to the server with the message "Ok.". The server reads two characters (but
+ the client sends three) and $ZKEY shows sockets with unread
+ characters.Please click Download sockexamplemulti3.m to download the
+ sockexamplemulti3.m program and follow instructions in the comments near
+ the top of the program file. You can also download sockexamplemulti3.m
+ from
+ http://tinco.pair.com/bhaskar/gtm/doc/books/pg/UNIX_manual/sockexamplemulti3.m.
- GT.M permits the SET command to modify the value of $ZINTERRUPT.
+ You can start a GT.M process in response to a connection request made
+ using inetd/xinetd. The following example uses inetd/xinetd to implement a
+ listener which responds to connections and messages just as the prior
+ example.
- If an interrupt handler changes the current IO device (via USE), it is the
- responsibility of the interrupt handler to restore the current IO device
- before returning. There are sufficient legitimate possibilities why an
- interrupt routine would want to change the current IO device (for example;
- daily log switching), that this part of the process context is not saved
- and restored automatically.
+ In the configuration file for xinetd, define a new service called
+ gtmserver. Set socket_type to "stream" and wait should be "no" as in the
+ following snippet:
- The initial value for $ZINTERRUPT is taken from the UNIX environment
- variable gtm_zinterrupt if it is specified, otherwise it defaults to the
- following string:
+ service gtmserver
+ {
+ disable = no
+ type = UNLISTED
+ port = 7777
+ socket_type = stream
+ wait = no
+ user = gtmuser
+ server = /path/to/startgtm
+ }
- IF $ZJOBEXAM()
+ If you define the server in /etc/services, the type and port options are
+ not needed. For more information, the xinetd.conf man page for more
+ details.
- The IF statement executes the $ZJOBEXAM function but effectively discards
- the return value.
+ If you are using inetd, a line should be added to /etc/inetd.conf with the
+ sockettype "stream", protocol "tcp", and the "nowait" flag should be
+ specified as in the example below, which assumes a gtmserver service is
+ defined in /etc/services:
- **Note**
+ gtmserver stream tcp nowait gtmuser /path/to/startgtm
- If the default value for $ZINTERRUPT is modified, no $ZJOBEXAM() will
- occur unless the replacement value directly or indirectly invokes that
- function. In other words, while $ZJOBEXAM() is part of the interrupt
- handling by default, it is not an implicit part of the interrupt handling.
+ In both of the above examples, "gtmuser" is the name of the user the
+ service gtmserver should be run as, and "/path/to/startgtm" is the name of
+ a script which defines some environment variables needed by GT.M before
+ starting it. Please check the man page for inetd.conf on your system since
+ the details may be slightly different.
-3 Interrupt_Handling
- Interrupt Handling
+ The minimum variables are $gtm_dist which should specify the directory
+ containing the GT.M distribution and $gtmroutines. As an example:
- GT.M process execution is interruptible with the following events:
+ #!/bin/bash
+ cd /path/to/workarea
+ export gtm_dist=/usr/local/gtm
+ export gtmroutines="/var/myApp/o(/var/myApp/r) $gtm_dist"
+ export gtmgbldir=/var/myApp/g/mumps.dat
+ $gtm_dist/mumps -r start^server
- When GT.M detects any of these events, it transfers control to a vector
- that depends on the event. For CTRAP characters and ZMAXTPTIME, GT.M uses
- the $ETRAP or $ZTRAP vectors described in more detail in the Error
- Processing chapter. For INTRPT and $ZTEXit, it XECUTEs the interrupt
- handler code placed in $ZINTERRUPT. If $ZINTERRUPT is an empty string,
- nothing is done in response to a MUPIP INTRPT. The default value of
- $ZINTERRUPT is "IF $ZJOBEXAM()" which redirects a dump of ZSHOW "*" to a
- file and reports each such occasion to the operator log. For CTRL+C with
- CENABLE, it enters Direct Mode to give the programmer control.
+ When start^server begins, the $PRINCIPAL device will already be connected
+ and $KEY will contain "ESTABLISHED|socket_handle|remote_ip_address". In
+ most cases, a USE should be executed to set various device parameters such
+ as delimiters.
- GT.M recognizes most of these events when they occur but transfers control
- to the interrupt vector at the start of each M line, at each iteration of
- a FOR LOOP, at certain points during the execution of commands which may
- take a "long" time. For example, ZWRITE, HANG, LOCK, MERGE, ZSHOW "V",
- OPENs of disk files and FIFOs, OPENs of SOCKETs with the CONNECT parameter
- (unless zero timeout,) WRITE /WAIT for SOCKETs, and READ for terminals,
- SOCKETs, FIFOs, and PIPEs. If +$ZTEXIT evaluates to a truth value at the
- outermost TCOMMIT or TROLLBACK, GT.M XECUTEs $ZINTERRUPT after completing
- the commit or rollback. CTRAP characters are recognized when they are
- typed on OpenVMS but when they are read on UNIX.
+ The ZSHOW "D" command reports available information on both the local and
+ remote sides of a TCP socket including local and remove addresses and
+ ports.
- If an interrupt event occurs in a long running external call (for example,
- waiting in a message queue), GT.M recognizes the event but makes the
- vector transfer after the external call returns when it reaches the next
- appropriate execution boundary.
+ 0 OPEN SOCKET TOTAL=1 CURRENT=0
+ SOCKET[0]=h11135182870 DESC=0 CONNECTED ACTIVE NOTRAP
+ REMOTE=10.1.2.3 at 53731 LOCAL=10.2.3.4 at 7777
+ ZDELAY ZIBFSIZE=1024 ZIBFSIZE=0
- When an interrupt handler is invoked, GT.M saves and restores the current
- values of $REFERENCE. However, the current device ($IO) is neither saved
- nor restored. If an interrupt handler changes $IO (via USE), ensure that
- the interrupt handler restores the current device before returning. To
- restore the device which was current when the interrupt handler began,
- specify USE without any deviceparameters. Any attempt to do IO on a device
- which was actively doing IO when the interrupt was recognized may result
- in a ZINTERCURSEIO error.
+2 I/O_Commands
+ I/O Commands
- Example:
+ This section describes the following GT.M I/O commands:
- set $zinterrupt="do ^interrupthandler($io)"
+ * OPEN establishes a connection from a GT.M process to a device.
+ * USE declares a device as the current source of input and destination
+ for output.
+ * READ accepts characters from the current device into a global or local
+ variable.
+ * WRITE sends characters to the current device.
+ * CLOSE breaks the connection between a GT.M process and a device.
- interrupthandler(currentdev)
- do ^handleinterrupt ; handle the interrupt
- use currentdev ; restore the device which was current when the interrupt was recognized
- quit
+3 Open
+ Open
- The use of the INTRPT facility may create a temporary hang or pause while
- the interrupt handler code is executed. For the default case where the
- interrupt handler uses IF $ZJOBEXAM() to create a dump, the pause duration
- depends on the number of local variables in the process at the time of the
- dump and on the speed of the disk being written to. The dumps are slower
- on a network-mounted disk than on a disk directly connected to the local
- system. Any interrupt driven code should be designed to account for this
- issue.
+ The OPEN command establishes a connection from a GT.M process to a device.
+
+ The format of the OPEN command is:
- **Important**
+ O[PEN][:tvexpr] expr[:[(keyword[=expr][:...])][:numexpr][:expr]][,...]
- Because sending an interrupt signal requires the sender to have
- appropriate permissions, the use of the job interrupt facility itself does
- not present any inherent security exposures. Nonetheless, because the dump
- files created by the default action contain the values of every local
- variable in the context at the time they are made, inappropriate access to
- the dump files would constitute a security exposure. Make sure the design
- and implementation of any interrupt logic includes careful consideration
- to security issues.
+ By default, when a device is unavailable, GT.M retries the OPEN
+ indefinitely at approximately one second intervals. A device is
+ unavailable when another process is using it exclusively, or when the
+ OPENing process does not have the resources left to open the device.
- During the execution of the interrupt handling code, $ZINITERRUPT
- evaluates to 1 (TRUE).
+ All other errors on OPEN raise an error condition and interrupt program
+ flow. A timeout is a tool that lets a GT.M routine regain program control
+ when a device remains unavailable. When the OPEN specifies a timeout, GT.M
+ keeps retrying until either the OPEN succeeds or the timeout expires.
- If an error occurs while compiling the $ZINTERRUPT code, the error handler
- is not invoked (the error handler is invoked if an error occurs while
- executing the $ZINTERRUPT code), GT.M sends the GTM-ERRWZINTR message and
- the compiler error message to the operator log facility. If the GT.M
- process is at a direct mode prompt or is executing a direct mode command
- (for example, a FOR loop), GT.M sends also sends the GTM-ERRWZINTR error
- message to the user console along with the compilation error. In both
- cases, the interrupted process resumes execution without performing any
- action specified by the defective $ZINTERRUPT vector.
+ If OPEN establishes a connection with a device before the timeout expires,
+ GT.M sets $TEST to TRUE (1). If the timeout expires, GT.M sets $TEST to
+ FALSE (0). If an OPEN command does not specify a timeout, the execution of
+ the command does not affect $TEST.
- If GT.M encounters an error during creation of the interrupt handler's
- stack frame (before transferring control to the application code specified
- by the vector), that error is prefixed with a GTM-ERRWZINTR error. The
- error handler then executes normal error processing associated with the
- interrupted routine.
+ If a process has not previously OPENed a device, any deviceparameters not
+ supplied on the OPEN take their default values. When reOPENing a device
+ that it previously closed, a GT.M process restores all characteristics not
+ specified on the OPEN to the values the device had when it was last
+ CLOSEd, except with SD, FIFO, and PIPE. If you have a menu-driven
+ application that OPENs and CLOSEs devices based on user selections, take
+ care that every OPEN explicitly includes all deviceparameters important to
+ the application.
- **Note**
+ GT.M treats sequential disk files differently and uses defaults for
+ unspecified sequential disk file characteristics on every OPEN (i.e., GT.M
+ does not retain sequential disk file characteristics on a CLOSE).
- The interrupt handler does not operate "outside" the current M environment
- but rather within the environment of the process.
+ If a process OPENs an already OPEN device, GT.M modifies any
+ characteristics that accept changes when a device is OPEN to reflect any
+ new deviceparameter specifications.
- TP transaction is in progress (0<$TLEVEL), updates to globals are not safe
- since a TP restart can be signaled at any time prior to the transaction
- being committed - even after the interrupt handler returns. A TP restart
- reverses all global updates and unwinds the M stack so it is as if the
- interrupt never occurred. The interrupt handler is not redriven as part of
- a transaction restart. Referencing (reading) globals inside an interrupt
- handler can trigger a TP restart if a transaction is active. When
- programming interrupt handling, either discard interrupts when 0<$TLEVEL
- (forcing the interrupting party to try again), or use local variables that
- are not restored by a TRESTART to defer the interrupt action until after
- the final TCOMMIT.
+ In UTF-8 mode, the OPEN command recognizes ICHSET, OCHSET, and CHSET as
+ three additional deviceparameters to determine the encoding of the the
+ input / output devices.
-2 $ZINInterrupt
- $ZINInterrupt
+ In M mode, the OPEN command ignores ICHSET, OCHSET, CHSET, and PAD device
+ parameters.
- $ZINI[NTERRUPT] evaluates to 1 (TRUE) when a process is executing code
- initiated by the interrupt mechanism, and otherwise 0 (FALSE).
+ If an I/O device uses a multi-byte character encoding, every READ and
+ WRITE operation of that device checks for well-formed characters according
+ to the specified character encoding with ICHSET or OCHSET. If the I/O
+ commands encounter an illegal sequence of bytes, they always trigger a
+ run-time error; a VIEW "NOBADCHAR" does not prevent such errors. Strings
+ created by $ZCHAR() and other Z equivalent functions may contain illegal
+ sequences. The only way to input or output such illegal sequences is to
+ specify character set "M" with one of these deviceparameters.
- GT.M does not permit the SET or NEW commands to modify $ZININTERRUPT.
+4 Examples_of_OPEN
+ Examples of OPEN
-2 $ZIO
- $ZIO
+ Example:
- $ZIO contains the translated name of the current device, in contrast to
- $IO, which contains the name as specified by the USE command.
+ set sd="report.dat" open sd:newversion
- GT.M does not permit the SET or NEW command to modify $ZIO.
+ This OPENs a NEWVERSION of a sequential disk file named report.dat for
+ both read and write access.
- An example where $ZIO contains a value different from $IO is if the
- environment variable gtm_principal is defined.
+4 OPEN_Deviceparameters
+ OPEN Deviceparameters
- Example:
+5 APPEND
+ APPEND
- $ gtm_principal="foo"
- $ export gtm_principal
- GTM>WRITE $IO
- foo
- GTM>WRITE $ZIO
- /dev/pts/8
+ APPEND Applies to: SD
- Notice that $ZIO contains the actual terminal device name while $IO
- contains the string pointed to by the environment variable gtm_principal.
+ APPEND Applies to: Sequential Files
-2 $ZJob
- $ZJob
+ Positions the file pointer at the end-of-file. This deviceparameter only
+ affects the device on the first OPEN command or OPEN command if the file
+ is CLOSEd NODESTROY. Re-OPENing an already OPEN device with this
+ deviceparameter has no effect. By default, OPEN sets the file pointer to
+ the beginning-of-file.
- $ZJ[OB] holds the pid of the process created by the last JOB command
- performed by the current process.
+ **Note**
- GT.M initializes $ZJOB to zero (0) at process startup. If the JOB command
- fails to spawn a new job, GT.M sets $ZJOB to zero (0). Note that because
- of the left to right evaluation order of M, using $ZJOB in the
- jobparameter string results in using the value created by the last, rather
- than the current JOB command, which is not likely to match common coding
- practice.
+ If an APPEND is combined with a SEEK deviceparameter the APPEND is done
+ first - regardless of deviceparameter order.
- GT.M does not permit the SET or NEW command to modify $ZJOB.
+ Example:
-2 $ZLevel
- $ZLevel
+ set sd="foo.txt"
+ open sd:(append:recordsize=70:wrap)
+ use sd
- $ZL[EVEL] contains an integer value indicating the "level of nesting"
- caused by DO commands, XECUTE commands, and extrinsic functions in the M
- invocation stack.
+ This example open file foo.txt and positions the file pointer at the end
+ of the file.
- $ZLEVEL has an initial value of one (1) and increments by one with each
- DO, XECUTE or extrinsic function. Any QUIT that does not terminate a FOR
- loop decrements $ZLEVEL. ZGOTO may also reduce $ZLEVEL. In accordance with
- the M standard, a FOR command does not increase $ZLEVEL. M routines cannot
- modify $ZLEVEL with the SET or NEW commands.
+5 ATTACH
+ ATTACH
- Use $ZLEVEL in debugging or in an error-handling mechanism to capture a
- level for later use in a ZGOTO argument.
+ ATTACH=expr Applies to: SOC
- Example:
+ Attach=expr Applies to: Socket Device
- GTM>zprint ^zleve
- zleve;
- do B
- write X,!
- quit
- B
- goto C
- quit
- C
- do D
- quit
- D
- set X=$ZLEVEL
- quit
+ ATTACH assigns expr as the handle name to the newly created socket. When
+ ATTACH is used and one of LISTEN or CONNECT is specified on the same OPEN,
+ the value of expr becomes the identifier of the newly created socket. If
+ neither LISTEN nor CONNECT is specified, ATTACH is ignored.
- GTM>do ^zleve
- 4
+ Example:
- GTM>
+ open tcpdev:(ichset="M":connect=hostname_":"_portno_":TCP":attach="client"):timeout:"SOCKET"
- This program, executed from Direct Mode, produces a value of 4 for
- $ZLEVEL. If you run this program from the shell, the value of $ZLEVEL is
- three (3).
+ This example uses the ATTACH deviceparameter to specify "client" as the
+ identifier of the newly created socket. Note that GT.M recognizes ICHSET
+ only in UTF-8 mode.
-2 $ZMAXTPTIme
- $ZMAXTPTIme
+5 CHSET
+ CHSET
- $ZMAXTPTI[ME] contains an integer value indicating the time duration GT.M
- should wait for the completion of all activities fenced by the current
- transaction's outermost TSTART/TCOMMIT pair.
+ CHSET=expr Applies to: All devices
- $ZMAXTPTIME can be SET but cannot be NEWed.
+ Establishes a common encoding for both input and output devices for the
+ device being OPENed in UTF-8 mode. The value of the expression can be M,
+ UTF-8, UTF-16, UTF-16LE, or UTF-16BE.
- $ZMAXTPTIME takes its value from the environment variable gtm_zmaxtptime.
- If gtm_zmaxtptime is not defined, the initial value of $ZMAXTPTIME is zero
- (0) seconds which indicates "no timeout" (unlimited time). The value of
- $ZMAXTPTIME when a transaction's outermost TSTART operation executes
- determines the timeout setting for that transaction.
+5 CONNECT
+ CONNECT
- When a $ZMAXTPTIME expires, GT.M executes the $ETRAP/$ZTRAP exception
- handler currently in effect.
+ CONNECT=expr Applies to: Socket Device
- **Note**
+ Creates a client connection with a server, which is located by the
+ information provided by expr. A new socket is allocated for the client
+ connection and is made the current socket for the device, if the operation
+ is successful.
- Negative values of $ZMAXTPTIME are also treated as "no timeout". Timeouts
- apply only to the outermost transaction, that is, $ZMAXTPTIME has no
- effect when TSTART is nested within another transaction.
+ expr specifies the protocol and the protocol-specific information.
+ Currently, GT.M supports TCP/IP and LOCAL (also known as UNIX domain)
+ socket protocols. For TCP/IP sockets, specify expr in the form of
+ "<host>:<port>:TCP", where host is an IPv4 or IPv6 address optionally
+ encapsulated by square-brackets ([]) like "127.0.0.1", "::1",
+ "[127.0.0.1]", or "[::1]" or a IPv4 or IPv6 hostname like
+ server.fis-gtm.com. When a hostname is specified, GT.M uses the IP version
+ of the first address returned by DNS:
- Example:
+ o that is supported by the operating system, and
+ o for which a network interface exists.
- Test;testing TP timeouts
- set $ZMAXTPTIME=6,^X=0,^Y=0,^Z=0
- write "Start with $ZMAXTPTIME=",$ZMAXTPTIME,":",!
- for sleep=3:2:9 do
- . set retlvl=$zl
- . do longtran;ztrap on longtran
- ;continues execution
- ;on next line
- . write "(^X,^Y)=(",^X,",",^Y,")",!
- write !,"Done TP Timeout test.",!
- quit
- longtran ;I/O in TP doesn't get rolled back
- set newzt="set $ZT="""" ";avoid recursive ZTRAP
- set $ZT=newzt_" goto err"
- tstart ():serial ;plain tstart works as well
- set ^X=1+^X
- write !,"^X=",^X,",will set ^Y to ",sleep
- write " in ",sleep," seconds..."
- hang sleep
- set ^Y=sleep
- write "^Y=",^Y
- tcommit
- write "...committed.",!
- quit
- err;
- set $ZT=""
- write !,"In $ZTRAP handler. Error was: "
- write !," ",$zstatus
- if $TLEVEL do ;test allows handler use outside of TP
- . trollback
- . write "Rolled back transaction."
- write !
- zgoto retlvl
+ For LOCAL sockets, specify expr in the form of "<pathname>:LOCAL", where
+ <pathname> is the name of the file to be used for communication.
+ <pathname> may contain a dollar sign ($) followed by the name of an
+ environment variable which GT.M expands in the same way as the device name
+ for a sequential file. The maximum allowed length of the expanded path
+ name depends on the OS.
- Results:
+ For LOCAL sockets, CONNECT attempts to open the specified file. If it
+ doesn't exist or there is no listener, CONNECT retries until it succeeds
+ or a specified timeout expires.
- Start with $ZMAXTPTIME=6:
+ **Note**
- ^X=1,will set ^Y to 3 in 3 seconds...^Y=3...committed.
+ CONNECT is not compatible with LISTEN.
- ^X=2,will set ^Y to 5 in 5 seconds...^Y=5...committed.
+ If the OPEN does not specify a timeout, a SOCKET OPEN waits for the
+ connection to complete or an event that terminates the attempt.
- ^X=3,will set ^Y to 7 in 7 seconds...
- In $ZTRAP handler. Error was:
- 150377322,longtran+7^tptime,%GTM-E-TPTIMEOUT, Transaction timeoutRolled back transaction.
+ Example:
- ^X=3,will set ^Y to 9 in 9 seconds...
+ open tcpdev:(connect=hostname_":"_portno_":TCP":attach="client":ioerror="TRAP"):timeout:"SOCKET"
- In $ZTRAP handler. Error was:
- 150377322,longtran+7^tptime,%GTM-E-TPTIMEOUT, Transaction timeoutRolled back transaction.
+ This example establishes a client connect with the server using the
+ connection string in the format of "hostname:port:TCP".
- Done TP Timeout test.
+5 DELIMITER
+ DELIMITER
-2 $ZMOde
- $ZMOde
+ [NO]DELIMITER=expr Applies to: SOC
- $ZMO[DE] contains a string value indicating the process execution mode.
+ DELIMITER establishes or replaces the list of delimiters used by the newly
+ created socket. The default is NODELIMITER. The delimiter list on a
+ preexisting device remains the same until it is explicitly replaced or
+ deleted.
- The mode can be:
+ expr is a string where the following characters have special
+ interpretation:
- * INTERACTIVE
- * OTHER
+ **Note**
- M routines cannot modify $ZMODE.
+ expr "ab:/:://:bc" is interpreted as four delimiters, which are "ab", ":",
+ "/", and "bc". One socket can have 0-64 delimiters and each delimiter can
+ contain 1-64 characters.
Example:
- GTM>WRITE $ZMODE
- INTERACTIVE
+ open tcpdev:(connect=host_":"_portno_":TCP":delim=$c(13):attach="client"):timeout:"SOCKET"
- This displays the process mode.
+ This command specifies $CHAR(13) as the delimiter for the socket tcpdev.
-2 $ZONLNrlbk
- $ZONLNrlbk
+5 EXCEPTION
+ EXCEPTION
- $ZONLNRLBK increments every time a process detects a concurrent MUPIP
- JOURNAL -ONLINE -ROLLBACK.
+ EXCEPTION=expr Applies to: All devices
- GT.M initializes $ZONLNRLBK to zero (0) at process startup. GT.M does not
- permit the SET or NEW commands to modify $ZONLNRLBK.
+ Defines an error handler for an I/O device. The expression must contain a
+ fragment of GT.M code (for example, GOTO ERRFILE) that GT.M XECUTEs when
+ GT.M detects an error, or an entryref to which GT.M transfers control, as
+ appropriate for the current gtm_ztrap_form.
-2 $ZPATNumeric
- $ZPATNumeric
+ A device EXCEPTION gets control after a non-fatal device error and
+ $ETRAP/$ZTRAP get control after other non-fatal errors.
- $ZPATN[UMERIC] is a read-only intrinsic special variable that determines
- how GT.M interprets the patcode "N" used in the pattern match operator.
+ For more information on error handling, refer to Chapter 13: "Err
+ Processing".
- With $ZPATNUMERIC="UTF-8", the patcode "N" matches any numeric character
- as defined by UTF-8 encoding. With $ZPATNUMERIC="M", GT.M restricts the
- patcode "N" to match only ASCII digits 0-9 (that is, ASCII 48-57). When a
- process starts in UTF-8 mode, intrinsic special variable $ZPATNUMERIC
- takes its value from the environment variable gtm_patnumeric. GT.M
- initializes the intrinsic special variable $ZPATNUMERIC to "UTF-8" if the
- environment variable gtm_patnumeric is defined to "UTF-8". If the
- environment variable gtm_patnumeric is not defined or set to a value other
- than "UTF-8", GT.M initializes $ZPATNUMERIC to "M".
+ Example:
+
+ open file:(EXCEPTION="s err=""open"" do error")
+
+ This example sets the following code to XECUTE when there is an error
+ while opening the file.
+
+ set err="open"
+ do error
- GT.M populates $ZPATNUMERIC at process initialization from the environment
- variable gtm_patnumeric and does not allow the process to change the
- value.
+5 EMPTERM
+ EMPTERM
- For characters in Unicode, GT.M assigns patcodes based on the default
- classification of the Unicode character set by the ICU library with three
- adjustments:
+ [NO]EMPT[ERM] Applies to: TRM
- 1. If $ZPATNUMERIC is not "UTF-8", non-ASCII decimal digits are
- classified as A.
- 2. Non-decimal numerics (Nl and No) are classified as A.
- 3. The remaining characters (those not classified by ICU functions:
- u_isalpha, u_isdigit, u_ispunct, u_iscntrl, 1), or 2) above) are
- classified into either patcode P or C. The ICU function u_isprint is
- used since is returns "TRUE" for non-control characters.
+ Allows an "Erase" character on an empty input line to terminate a READ or
+ READ # command. The default is NOEMPTERM. The gtm_principal_editing
+ environment variable specifies the initial setting of [NO]EMPTERM. The
+ TERMINFO specified by the current value of the TERM environment variable
+ defines capnames values "kbs" and/or "kdch1" with character sequences for
+ "Erase." If "kbs" or "kdch1" are multi-character values, you must also
+ specify the ESCAPE or EDIT deviceparameters for EMPTERM recognition.
- The following table contains the resulting Unicode general category to M
- patcode mapping:
+ The erase character as set and shown by stty also terminates a READ
+ command with an empty input line. You can set this erase character to
+ various values using the stty shell command. Typical values of an erase
+ character are <CTRL-H> and <CTRL-?>. Characters set and shown with stty
+ setting must match what the terminal emulator sends.
- +------------------------------------------------------------------------+
- | Unicode General Category | GT.M patcode Class |
- |------------------------------+-----------------------------------------|
- | L* (all letters) | A |
- |------------------------------+-----------------------------------------|
- | M* (all marks) | P |
- |------------------------------+-----------------------------------------|
- | Nd (decimal numbers) | N (if decimal digit is ASCII or |
- | | $ZPATNUMERIC is "UTF-8", otherwise A |
- |------------------------------+-----------------------------------------|
- | Nl (letter numbers) | A (examples of Nl are Roman numerals) |
- |------------------------------+-----------------------------------------|
- | No (other numbers) | A (examples of No are fractions) |
- |------------------------------+-----------------------------------------|
- | P* (all punctuation) | P |
- |------------------------------+-----------------------------------------|
- | S* (all symbols) | P |
- |------------------------------+-----------------------------------------|
- | Zs (spaces) | P |
- |------------------------------+-----------------------------------------|
- | Zl (line separators) | C |
- |------------------------------+-----------------------------------------|
- | Zp (paragraph separators) | C |
- |------------------------------+-----------------------------------------|
- | C* (all control code points) | C |
- +------------------------------------------------------------------------+
+ The environment variable TERM must specify a terminfo entry that matches
+ both what the terminal (or terminal emulator) sends and expects.
- For a description of the Unicode general categories, refer to
- http://unicode.org/charts/.
+5 FIFO
+ FIFO
+
+ FIFO Applies to: FIFO
+
+ FIFO Applies to: FIFO
+
+ Specifies that the device for the OPEN is a FIFO name. GT.M creates the
+ FIFO if it does not already exist and if the process has adequate
+ privileges. However, in the event that the process does not have adequate
+ privileges, the process generates a run-time error. A process does not
+ require any special privileges to OPEN an existing FIFO. The FIFO needs to
+ be readable (or writeable) just like any other file.
Example:
- GTM>write $zpatnumeric
- UTF-8
- GTM>Write $Char($$FUNC^%HD("D67"))?.N ; This is the Malayalam decimal digit 1
- 1
- GTM>Write 1+$Char($$FUNC^%HD("D67"))
- 1
- GTM>Write 1+$Char($$FUNC^%HD("31")) ; This is the ASCII digit 1
- 2
+ open file:(fifo:read:recordsize=1048576):100
-2 $ZPOSition
- $ZPOSition
+5 FIXED
+ FIXED
- $ZPOS[ITION] contains a string value specifying the current entryref,
- where entryref is [label][+offset]^routine, and the offset is evaluated
- from the closest preceding label.
+ [NO]FIXED Applies to: SD FIFO PIPE
- GT.M does not permit the SET or NEW commands to modify $ZPOSITION.
+ [NO]FIXED Applies to: SD FIFO PIPE
- Example:
+ Selects a fixed-length record format for sequential disk files. FIXED does
+ not specify the actual length of a record. Use RECORDSIZE to specify the
+ record length.
- GTM>WRITE !,$ZPOS,! ZPRINT @$ZPOS
+ NOFIXED specifies a variable-length record format for sequential disk
+ files. NOFIXED is a synonym for VARIABLE. FIXED is incompatible with
+ STREAM and VARIABLE. By default, records have VARIABLE length record
+ format.
- This example displays the current location followed by the source code for
- that line.
+ **Note**
-2 $ZPROMpt
- $ZPROMpt
+ FIXED length records do not implicitly use embedded record terminators
+ such as line feeds.
- $ZPROM[PT] contains a string value specifying the current Direct Mode
- prompt. By default, GTM>is the Direct Mode prompt. M routines can modify
- $ZPROMPT by means of a SET command. $ZPROMPT cannot exceed 16 characters.
- If an attempt is made to assign $ZPROMPT to a longer string, only the
- first 16 characters will be taken.
+ In UTF-8 mode, GT.M I/O enforces a more record-oriented view of the file,
+ treating each record as RECORDSIZE bytes long. Note that a Unicode
+ code-point never splits across records. If a multi-byte character (when
+ CHSET is UTF-8) or a surrogate pair (when CHSET is UTF-16) does not fit
+ into the record (either logical as given by WIDTH or physical as given by
+ RECORDSIZE), the WRITE command uses the byte values as specified by the
+ PAD deviceparameter to fill the physical record. A combining character may
+ end up in the subsequent record if it does not fit in the current record.
- In UTF-8 mode, if the 31st byte is not the end of a valid UTF-8 character,
- GT.M truncates the $ZPROMPT value at the end of last character that
- completely fits within the 31 byte limit.
+ **Note**
- The environment gtm_prompt initializes $ZPROMPT at process startup.
+ PAD is effective only for devices opened with a Unicode CHSET. In M mode
+ PAD is always <SP>
+
+ Example:
+
+ GTM>do ^fixedex
+ fixedex;
+ zprint ^fixedex
+ set file="fix.txt"
+ open file:(newversion:fixed:recordsize=4)
+ use file
+ write "Hello, World",!
+ close file
+ set file="fixnowrap.txt"
+ open file:(newversion:fixed:recordsize=4:nowrap)
+ use file
+ write "Hel",!
+ write "lo, World",! ; This writes only 'lo, '
+ close file
+ zsystem ("more fix*.txt")
+ zsystem ("od -cb fix.txt")
+ zsystem ("od -cb fixnowrap.txt")
+ quit
+ ::::::::::::::
+ fix.txt
+ ::::::::::::::
+ Hello, World
+ ::::::::::::::
+ fixnowrap.txt
+ ::::::::::::::
+ Hel lo,
+ 0000000 H e l l o , W o r l d
+ 110 145 154 154 157 054 040 127 157 162 154 144
+ 0000014
+ 0000000 H e l l o ,
+ 110 145 154 040 154 157 054 040
+ 0000010
Example:
- GTM>set $zprompt="Test01">"
- Test01>set $zprompt="GTM>"
+ GTM>zprint ^gtmcp
+ gtmcp ; Copy a binary file using GT.M
+ new dest,line,max,src
+ if 2>$length($zcmdline," ") write "$gtm_dist/mumps -r source target",!
+ set dest=$piece($zcmdline," ",2)
+ set src=$piece($zcmdline," ",1)
+ set max=1024*1024 ; the maximum GT.M string size
+ open src:(readonly:FIXED:WRAP:CHSET="M") ;
+ open dest:(newversion:FIXED:WRAP:CHSET="M") ; use FIXED format because it does not insert carriage control characters after $X reaches its maximum value.
+ for use src read line#max quit:$zeof use dest write line
+ close src
+ use dest
+ set $x=0
+ close dest
+ quit
- This example changes the GT.M prompt to Test01> and then back to GTM>.
+ This example copies a binary file using GT.M.
-2 $ZREalstor
- $ZREalstor
+5 FOLLOW
+ FOLLOW
- $ZREALSTOR contains the total memory (in bytes) allocated by the GT.M
- process, which may or may not actually be in use. It provides one view
- (see also $ZALLOCSTOR and ZUSEDSTOR) of the process memory utilization and
- can help identify storage related problems. GT.M does not permit
- $ZREALSTOR to be SET or NEWed.
+ [NO]FOLLOW Applies to: SD
-2 $ZROutines
- $ZROutines
+ Configures READ to return only when it has a complete record or reaches
+ any specified timeout; it waits for more input rather than terminating on
+ an EOF (end-of-file) condition.
- $ZRO[UTINES] contains a string value specifying a directory or list of
- directories containing object files. Each object directory may also have
- an associated directory, or list of directories, containing the
- corresponding source files. These directory lists are used by certain GT.M
- functions, primarily auto-ZLINK, to locate object and source files. The
- order in which directories appear in a given list determines the order in
- which they are searched for the appropriate item.
+ The USE command can switch a device from NOFOLLOW to FOLLOW or from FOLLOW
+ to NOFOLLOW. This provides a READ mode of operation similar to a tail -f
+ in UNIX.
- Searches that use $ZROUTINES treat files as either object or source files.
- GT.M treats files with an extension of .o as object files and files with
- an extension of .m as source files.
+5 GROUP
+ GROUP
- **Note**
+ GROUP=expr Applies to: SOC(LOCAL) SD FIFO
- Paths used in $ZROUTINES to locate routines must not include embedded
- spaces, as $ZROUTINES uses spaces as delimiters.
+ Specifies access permission on a UNIX file for other users in the file
+ owner's group. The expression is a character string evaluating to null or
+ to any combination of the letters RWX, indicating respectively Read,
+ Write, and eXecute access. When permission controlling deviceparameters
+ (OWNER,GROUP,WORLD) appears on an OPEN of a new file, any user category
+ (OWNER, SYSTEM, WORLD), that is not explicitly specified is given the
+ default access permissions. When any one of these deviceparameters appears
+ on an OPEN of an existing device, any user category that is not explicitly
+ specified remains unchanged.
-3 Establishing_the_Value_from_$gtmroutines
- Establishing the Value from $gtmroutines
+ In order to modify file security, the user who issues the OPEN must have
+ ownership.
- When the environment variable gtmroutines is defined, GT.M initializes
- $ZROUTINES to the value of gtmroutines. Otherwise, GT.M initializes
- $ZROUTINES to a null value. When $ZROUTINES is null, GT.M attempts to
- locate all source and object files in the current working directory.
- $ZROUTINES="" is equivalent to $ZROUTINES=".".
+ If none of GROUP, SYSTEM, OWNER, or WORLD are specified on OPEN, GT.M does
+ not modify the permissions on an existing file and new files are created
+ using the standard UNIX rules.
- Commands or functions such as DO, GOTO, ZGOTO, ZBREAK, ZPRINT, and $TEXT
- may auto-ZLINK and thereby indirectly use $ZROUTINES. If their argument
- does not specify a directory, ZEDIT and explicit ZLINK use $ZROUTINES.
- ZPRINT and $TEXT use $ZROUTINES to locate a source file if GT.M cannot
- find the source file pointed to by the object file.
+ Example:
-3 Setting_a_Value_for_$ZROutines
- Setting a Value for $ZROutines
+ open "test52.txt":(append:group="rw")
- $ZRO[UTINES] is a read-write Intrinsic Special Variable, so M can also SET
- the value.
+ This examples open file test52.txt in append mode with Read Write group
+ access. Note that the user who opens file text52.txt must have ownership
+ permissions for it.
- By default, each directory entry in $ZROUTINES is assumed to contain both
- object and source files. However, each object directory may have an
- associated directory or list of directories to search for the
- corresponding source files. This is done by specifying the source
- directory list, in parentheses, following the object directory
- specification.
+5 ICHSET
+ ICHSET
- If the command specifies more than one source directory for an object
- directory, the source directories must be separated by spaces, and the
- entire list must be enclosed in parentheses ( ) following the object
- directory-specification. If the object directory should also be searched
- for source, the name of that directory must be included in the
- parentheses, (usually as the first element in the list).
- Directory-specifications may also include empty parentheses, directing
- GT.M to proceed as if no source files exist for objects located in the
- qualified directory.
+ ICHSET=expr Applies to: All devices
- To set $ZROUTINES outside of M, use the appropriate shell command to set
- gtmroutines. Because gtmroutines is a list, enclose the value in quotation
- marks (" ").
+ Establishes the character encoding of the input device being OPENed in the
+ UTF-8 mode. The value of the expression can be M, UTF-8, UTF-16, UTF-16LE,
+ or UTF-16BE. In M mode, ICHSET has no effect.
- Changes to the value of $ZROUTINES during a GT.M invocation only last for
- the current invocation, and do not change the value of gtmroutines.
+ If ICHSET is not specified, GT.M assumes UTF-8 as the default character
+ set for input from the device.
- Directory specifications may include an environment variable. When GT.M
- SETs $ZROUTINES, it translates all environment variables and verifies the
- syntax and the existence of all specified directories. If $ZROUTINES is
- set to an invalid value, GT.M generates a run-time error and does not
- change the value of $ZROUTINES. Because the environment variables are
- translated when $ZROUTINES is set, any changes to their definition have no
- effect until $ZROUTINES is set again.
+ If expr is set to a value other than M, UTF-8, UTF-16, UTF-16LE or
+ UTF-16BE, GT.M produces a run-time error. UTF-16, UTF-LE, and UTF-16BE are
+ not supported for $Principal and Terminal devices.
-3 $ZROutines_Examples
- $ZROutines Examples
+ **Note**
- Example:
+ ICHSET is a deviceparameter of the OPEN command and not the USE command.
+ Since GT.M implicitly OPENs $PRINCIPAL before any application code is
+ executed, ICHSET does not apply to $Principal.
- GTM>s $zroutines=".(../src) $gtm_dist"
+5 INDEPENDENT
+ INDEPENDENT
- This example directs GTM to look for object modules first in your current
- directory, then in the distribution directory that contains the percent
- routines. GT.M locates sources for objects in your current directory in
- the sibling /src directory.
+ INDEPENDENT Applies to: PIPE
- Example:
+ The INDEPENDENT deviceparameter specifies that the newly created process
+ will not be terminated by the CLOSE of the device. The input and output of
+ INDEPENDENT processes should be handled in such a way that it runs
+ independently even after the CLOSE of the device. By default, CLOSE
+ terminates the process associated with the PIPE device.
- $ gtmroutines="/usr/jones /usr/smith"
- $ export gtmroutines
- $ gtm
- GTM>write $zroutines
- "/usr/jones /usr/smith"
- GTM>set $zro="/usr/jones/utl /usr/smith/utl"
- GTM>write $zroutines
- "/usr/jones/utl /usr/smith/utl"
- GTM>halt
- $ echo $gtmroutines
- /usr/jones /usr/smith
+5 IKEY
+ IKEY
- This example defines the environment variable gtmroutines. Upon entering
- GT.M Direct Mode $zroutines has the value supplied by gtmroutines. The SET
- command changes the value. When the GT.M image terminates, the shell echo
- command demonstrates that gtmroutines has not been modified by the M SET
- command.
+ Applies to: SD, PIPE, and FIFO
- Example:
+ IKEY allows the use of a seperate key for READ to a device; for example,
+ when a GT.M process is an element of a UNIX pipe. The format of the IKEY
+ deviceparameter is:
- GTM>SET $ZRO=". /usr/smith"
+ IKEY="key_name [IV]"
- This example sets $zroutines to a list containing two directories.
+ key_name is case-sensitive and must match a key name in the "files"
+ section of the gtmcrypt_config file. The optional IV specifies an
+ initialization vector to use for encryption and decryption.
- Example:
+ For more information, refer to the description of KEY deviceparameter of
+ OPEN or USE.
- GTM>set $zro="/usr/smith(/usr/smith/tax /usr/smith/fica)"
+5 IOERROR
+ IOERROR
- This example specifies that GT.M should search the directory /usr/smith
- for object files, and the directories /usr/smith/tax and /usr/smith/fica
- for source files. Note that in this example. GT.M does not search
- /usr/smith for source files.
+ IOERROR=expr Applies to: SOC
- Example:
+ Enables exception handling in socket devices. expr specifies the I/O error
+ trapping mode. A value equal to "TRAP" specifies that I/O errors on a
+ device raise error conditions. A value equal to "NOTRAP", or when IOERROR
+ is not specified, indicates that I/O error on a device does not raise
+ error conditions.
- GTM>set $zro="/usr/smith(/usr/smith /usr/smith/tax /usr/smith/fica)"
+ **Note**
- This example specifies that GT.M should search the directory /usr/smith
- for object files and the directories /usr/smith/tax and /usr/smith/fica
- for source files. Note that the difference between this example and the
- previous one is that GT.M searches /usr/smith for both object and source
- files.
+ The IOERROR setting is associated with sockets while EXCEPTION is
+ associated with the SOCKET device. In other words, IOERROR can be turned
+ on or off for each of the sockets associated with a SOCKET device but
+ there is only one EXCEPTION value which is used for all the sockets.
Example:
- GTM>set $zro="/usr/smith /usr/smith/tax() /usr/smith/fica"
+ open sock:(connect=host_":"_port_":TCP":delim=$char(13,10):ioerror="TRAP")::"SOCKET"
- This specifies that GT.M should search /usr/smith and /usr/smith/fica for
- object and source files. However, because the empty parentheses indicate
- directories searched only for object files, GT.M does not search
- /usr/smith/tax for source files.
+ This example opens a socket connection and specifies that I/O errors on
+ the device raises error conditions.
- Omitting the parentheses indicates that GT.M can search the directory for
- both source and object files. $ZROUTINES=/usr/smith is equivalent to
- $ZROUTINES=/usr/smith(/usr/smith).
+5 LISTEN
+ LISTEN
-3 $ZROutines_Search_Types
- $ZROutines Search Types
+ LISTEN=expr Applies to: SOC
- GT.M uses $ZRO[UTINES] to perform three types of searches:
+ A new socket is allocated to listen for a connection. It is made the
+ current socket for the device, if the operation is successful. Upon
+ successful completion, $KEY is set to the format of
+ "LISTENING|<socket_handle>|{<portnumber>|</path/to/LOCAL_socket>}"
+ otherwise, $KEY is assigned the empty string.
- * Object-only when the command or function using $ZROUTINES requires a
- .o file extension.
- * Source-only when the command or function using $ZROUTINES requires a
- file extension other than .o.
- * Object-source match when the command or function using $ZROUTINES does
- not specify a file extension.
+ expr specifies the protocol and protocol specific information. Currently,
+ GT.M supports TCP/IP and LOCAL (also known as UNIX domain) socket
+ protocols. For TCP/IP sockets, specify expr in the form of "<port>:TCP".
- An explicit ZLINK that specifies a non .OBJ .o extension is considered as
- a function that has not specified a file extension for the above searching
- purposes.
+ If <port>=0 is specified, the system chooses the port for the TCP/IP
+ socket.
- All searches proceed from left to right through $ZROUTINES. By default,
- GT.M searches directories for both source and object files. GT.M searches
- directories followed by empty parentheses ( ) for object files only. GT.M
- searches directories in parentheses only for source files.
+ For LOCAL sockets:
- Once an object-matching search locates an object file, the source search
- becomes limited. If the directory containing the object file has an
- attached parenthetical list of directories, GT.M only searches the
- directories in the attached list for matching source files. If the
- directory containing the object files does not have following parentheses,
- GT.M restricts the search for matching source files to the same directory.
- If the object module is in a directory qualified by empty parentheses,
- GT.M cannot perform any operation that refers to the source file.
+ o Specify expr in the form of "<pathname>:LOCAL", where <pathname> is
+ the name of the file to be used for communication. <pathname> may
+ contain a dollar sign ($) followed by the name of an environment
+ variable which GT.M expands in the same way as the device name for a
+ sequential file. The maximum allowed length of the expanded path name
+ depends on the OS.
+ o LISTEN creates the file if it doesn't exist. If the OPEN command
+ specifies the NEWVERSION deviceparameter, the file specified by the
+ pathname exists, and is a socket file, that file is deleted and GT.M
+ creates a new file.
+ o LISTEN with an OPEN processes the GROUP, OWNER, SYSTEM, WORLD, UIC,
+ and NEWVERSION deviceparameters the same as OPEN for sequential files.
- The following table shows GT.M commands and functions using $ZROUTINES and
- the search types they support.
+5 MOREREADTIME
+ MOREREADTIME
- +------------------------------------------------------+
- | GT.M Commands and $ZROUTINES Search Types |
- |------------------------------------------------------|
- | SEARCH/ | FILE | |
- | FUNCTION | EXTENSION | SEARCH TYPE |
- | | SPECIFIED | |
- |------------+-----------+-----------------------------|
- | | | OBJ-ONLY | SRC-ONLY | MATCH |
- |------------+-----------+----------+----------+-------|
- | EXPLICIT | | | | |
- | | .o | X | | |
- | ZLINK | | | | |
- |------------+-----------+----------+----------+-------|
- | | Not .o | | | X |
- |------------+-----------+----------+----------+-------|
- | | None | | | X |
- |------------+-----------+----------+----------+-------|
- | AUTO-ZLINK | None | | | X |
- |------------+-----------+----------+----------+-------|
- | ZEDIT | Not .o | | X | |
- |------------+-----------+----------+----------+-------|
- | ZPRINT | None | | X | |
- |------------+-----------+----------+----------+-------|
- | $TEXT | None | | X | |
- +------------------------------------------------------+
+ MOREREADTIME=intexpr Applies to: SOC
+
+ MOREREADTIME specifies the polling interval (in milliseconds) that a
+ SOCKET device uses to check for arriving packets.
+
+ With no MOREREADTIME specified, SOCKET READ implements a dynamic approach
+ of using a longer first interval of 200 ms when it finds no data, then
+ shortening the interval to 10 ms when data starts to arrive.
+
+ If an interval is specified, the SOCKET device always uses the specified
+ interval and doesn't adjust dynamically. This applies to any SOCKET READ.
+
+ If a SOCKET READ is not subject to any of the defined terminating
+ conditions, it terminates either after it has at least one character
+ followed by an interval with no new packets, or reading 1,048,576 bytes.
+
+ Example:
- If ZPRINT or $TEXT() require a source module for a routine that is not in
- the current image, GT.M first performs an auto-ZLINK with a matching
- search.
+ Use tcpdev:morereadtime=200
- ZPRINT or $TEXT locate the source module using a file specification for
- the source file located in the object module. If GT.M finds the source
- module in the directory where it was when it was compiled, the run-time
- system does not use $ZROUTINES. If GT.M cannot find the source file in the
- indicated location, the run-time system uses $ZROUTINES.
+ This example specifies that all READs for socket device tcpdev must wait
+ for 200 milliseconds for input.
-3 $ZROutines_Search_Examples
- $ZROutines Search Examples
+5 NEWVERSION
+ NEWVERSION
- This section describes a model for understanding $ZROUTINES operations and
- the illustrating examples, which may assist you if you wish to examine the
- topic closely.
+ NEWVERSION Applies to: SD FIFO SOC(LOCAL)
- You may think of $ZROUTINES as supplying a two dimensional matrix of
- places to look for files. The matrix has one or more rows. The first row
- in the matrix contains places to look for object and the second and
- following rows contain places to look for source. Each column represents
- the set of places that contain information related to the object modules
- in the first row of the column.
+ The NEWVERSION deviceparameter assures that when an existing file is used,
+ it is empty upon the OPEN.
+
+ By default, if any version of the file exists, OPEN accesses the current
+ version. If no version of the file exists, OPEN without READONLY creates a
+ new file.
Example:
- GTM>s $zro=". /usr/smi/utl() /usr/jon/utl
- (/usr/jon/utl/so /usr/smi/utl)"
+ GTM>file1="foo.txt"
+ GTM>open file1:newversion:recordsize=5000
- The following table illustrates the matrix view of this $ZROUTINES.
+ GTM>
- +--------------------------------------------------------+
- | $ZROUTINES Search Matrix |
- |--------------------------------------------------------|
- | SEARCH FOR | Column 1 | Column 2 | Column 3 |
- |------------+----------+--------------+-----------------|
- | OBJECTS | . | /usr/smi/utl | /usr/jon/utl |
- |------------+----------+--------------+-----------------|
- | SOURCE | . | | /usr/jon/utl/so |
- |------------+----------+--------------+-----------------|
- | | | | /usr/smi/utl |
- +--------------------------------------------------------+
+ This example creates a new version of sequential file foo.txtwith
+ RECORDSIZE of 5000 bytes.
- To perform object-only searches, GT.M searches only the directories or
- object libraries in the top 'objects' row for each column starting at
- column one. If GT.M does not locate the object file in a directory or
- object library in the 'objects' row of a column, GT.M begins searching
- again in the next column. If GT.M cannot locate the file in any of the
- columns, it issues a run-time error.
+ Example:
- As illustrated in the preceding table, GT.M searches for object files in
- the directories . ,/usr/smi/utl and /usr/jon/utl.
+ GTM>set delim=$c(13)
+ GTM>set tcpdev="server$"_$j,timeout=30
+ GTM>open tcpdev:(LISTEN="local.socket"_":LOCAL":delim=$c(13):attach="server":newversion):timeout:"SOCKET"
- To perform source-only searches, GT.M looks down to the 'source' row at
- the bottom of each column, excluding columns headed by object-only
- directories (that is, those object directories, which consist of an empty
- list of source directories) or object libraries. If GT.M cannot locate the
- source file in the 'source' row of a column, it searches the next eligible
- column.
+ This example deletes the old local.socket file (if it exists) and creates
+ a new LISTENING local.socket file.
- To perform object-source match searches, GT.M looks at each column
- starting at column one. GT.M does an object-only search in the 'objects'
- row of a column and a source-only search in the 'source' row(s) of a
- column. If GT.M locates either the object-file or the souce-file, the
- search is completed. Else, GT.M starts searching the next column. If GT.M
- cannot locate either the object file or the source file in any of the
- columns, it issues a run-time error.
+5 OCHSET
+ OCHSET
- As illustrated in the preceding table, GT.M searches for source-files in
- the directory "." in column one. If GT.M cannot locate the source file in
- ".", it omits column two because it is an object-only directory and
- instead searches column three. Since column three specifies
- /usr/jon/utl/so and /usr/smi/utl, GT.M searches for the source-file in
- these directories in column three and not in /usr/jon/utl. If GT.M cannot
- locate the source-file in column three, it terminates the search and
- issues a run-time error.
+ OCHSET=expr Applies to: All devices
- Once the object-source match search is done, GT.M now has either the
- object-file or source-file or both available. GT.M then recompiles the
- source-file based on certain conditions, before linking the object-file
- into the current image.
+ Establishes the character encoding of the output device being OPENed in
+ the UTF-8 mode. The value of the expression can be M, UTF-8, UTF-16,
+ UTF-16LE, or UTF-16BE. In M mode, OCHSET has no effect.
- If auto-ZLINK or ZLINK determines that the source file requires
- [re]compilation, GT.M places the object file in the above object directory
- in the same column as the source file. For example, if GT.M locates the
- source file in /usr/smi/utl in column three, GT.M places the resultant
- object file in /usr/jon/utl.
+ If *CHSET is not specified, GT.M assumes UTF-8 as the default character
+ set for all the input / output devices.
-3 Shared_Library_File_Specification_in_$ZROUTINES
- Shared Library File Specification in $ZROUTINES
+ If expr is set to a value other than M, UTF-8, UTF-16, UTF-16LE or
+ UTF-16BE, GT.M produces a run-time error. UTF-16, UTF-LE, and UTF-16BE are
+ not supported for $Principal and Terminal devices.
- The $ZROUTINES ISV allows individual UNIX shared library file names to be
- specified in the search path. During a search for auto-ZLINK, when a
- shared library is encountered, it is probed for a given routine and, if
- found, that routine is linked/loaded into the image. During an explicit
- ZLINK, all shared libraries in $ZROUTINES are ignored and are not searched
- for a given routine.
+ **Note**
- $ZROUTINES syntax contains a file-specification indicating shared library
- file path. GT.M does not require any designated extension for the shared
- library component of $ZROUTINES. Any file specification that does not name
- a directory is treated as shared library. However, it is recommended that
- the extension commonly used on a given platform for shared library files
- be given to any GT.M shared libraries. A shared library component cannot
- specify source directories. GT.M reports an error at an attempt to
- associate any source directory with a shared library in $ZROUTINES.
+ OCHSET is a deviceparameter of the OPEN command not the USE command. Since
+ GT.M implicitly OPENs $PRINCIPAL before any application code is executed,
+ OCHSET does not apply to $Principal.
- The following traits of $ZROUTINES help support shared libraries:
+ Example:
- * The $ZROUTINES search continues to find objects in the first place,
- processing from left to right, that holds a copy; it ignores any
- copies in subsequent locations. However, now for auto-ZLINK, shared
- libraries are accepted as object repositories with the same ability to
- supply objects as directories.
- * Explicit ZLINK, never searches Shared Libraries. This is because
- explicit ZLINK is used to link a newly created routine or re-link a
- modified routine and there is no mechanism to load new objects into an
- active shared library.
- * ZPRINT and $TEXT() of the routines in a shared library, read source
- file path from the header of the loaded routine. If the image does not
- contain the routine, an auto-ZLINK is initiated. If the source file
- path recorded in the routine header when the module was compiled
- cannot be located, ZPRINT and $TEXT() initiate a search from the
- beginning of $ZROUTINES, skipping over the shared library file
- specifications. If the located source does not match the code in image
- (checked via checksum), ZPRINT generates an object-source mismatch
- status and $TEXT() returns a null string.
- * ZEDIT, when searching $ZROUTINES, skips shared libraries like explicit
- ZLINK for the same reasons. $ZSOURCE ISV is implicitly set to the
- appropriate source file.
+ GTM>SET file1="mydata.out"
- For example, if libshare.so is built with foo.o compiled from
- ./shrsrc/foo.m, the following commands specify that GT.M should search the
- library ./libshare.so for symbol foo when do ^foo is encountered.
+ GTM>SET expr="UTF-16LE"
- GTM>SET $ZROUTINES="./libshare.so ./obj(./shrsrc)"
- GTM>DO ^foo;auto-ZLINK foo - shared
- GTM>ZEDIT "foo";edit ./shrsrc/foo.m
- GTM>W $ZSOURCE,!;prints foo
- GTM>ZPRINT +0^foo;issues a source-object mismatch status TXTSRCMAT error message
- GTM>ZLINK "foo";re-compile ./shrsrc/foo.m to generate ./obj/foo.o.
- GTM>W $TEXT(+0^foo);prints foo
+ GTM>OPEN file1:(ochset=expr)
- Note that ZPRINT reports an error, as foo.m does not match the routine
- already linked into image. Also note that, to recompile and re-link the
- ZEDITed foo.m, its source directory needs to be attached to the object
- directory [./obj] in $ZROUTINES. The example assumes the shared library
- (libshare.so) has been built using shell commands.
+ GTM>SET DS=$CHAR($$FUNC^%HD("0905"))_$CHAR($$FUNC^%HD("091A"))
-2 $ZSOurce
- $ZSOurce
+ GTM>SET DS=DS_$CHAR($$FUNC^%HD("094D"))_$CHAR($$FUNC^%HD("091B"))_$CHAR($$FUNC^%HD("0940"))
- $ZSO[URCE] contains a string value specifying the default pathname for the
- ZEDIT and ZLINK commands. ZEDIT or ZLINK without an argument is equivalent
- to ZEDIT/ZLINK $ZSOURCE.
+ GTM>USE file1 WRITE DS,!
- $ZSOURCE initially contains the null string. When ZEDIT and ZLINK commands
- have a pathname for an argument, they implicitly set $ZSOURCE to that
- argument. This ZEDIT/ZLINK argument can include a full pathname or a
- relative one. A relative path could include a file in the current
- directory, or the path to the file from the current working directory. In
- the latter instance, do not include the slash before the first directory
- name. $ZSOURCE will prefix the path to the current working directory
- including that slash.
+ GTM>CLOSE file1
- The file name may contain a file extension. If the extension is .m or .o,
- $ZSOURCE drops it. The ZEDIT command accepts arguments with extensions
- other than .m or .o. $ZSOURCE retains the extension when such arguments
- are passed.
+ This example opens a new file called mydata.out and writes Devanagari
+ characters in the UTF-16LE encoding.
- If $ZSOURCE contains a file with an extension other than .m or .o, ZEDIT
- processes it but ZLINK returns an error message
+5 OWNER
+ OWNER
- $ZSOURCE is a read-write Intrinsic Special Variable, (i.e., it can appear
- on the left side of the equal sign (=) in the argument to the SET
- command). A $ZSOURCE value may include an environment variable. GT.M
- handles logical names that translate to other logical names by performing
- iterative translations according to VMS conventions. If a logical name
- translates to a VMS search list, GT.M uses only the first name in the
- list.
+ OWNER=expr Applies to: SOC(LOCAL) SD FIFO
- Example:
+ Specifies access permission on a UNIX file for the owner of the file. The
+ expression is a character string evaluating to null or to any combination
+ of the letters RWX, indicating Read, Write, and eXecute access. When any
+ one of these deviceparameters appears on an OPEN of a new file, any user
+ category that is not explicitly specified is given the default mask. When
+ any one of these deviceparameters (OWNER, GROUP, , WORLD) appears on an
+ OPEN of an existing file, any user category that is not explicitly
+ specified remains unchanged.
- GTM>ZEDIT "subr.m"
- .
- .
- GTM>WRITE $ZSOURCE
+ To modify file security, the user who issues the OPEN must have ownership.
- subr
+ If none of GROUP, SYSTEM, OWNER, or WORLD are specified on OPEN, GT.M does
+ not modify the permissions on an existing file and new files are created
+ using the standard UNIX rules.
Example:
- GTM>ZEDIT "test"
- .
- .
- .
- GTM>WRITE $ZSOURCE
+ open "test49.txt":(newversion:owner="rw":group="rw":world="rw")
- "test"
+ This example opens a new version of test49.txt with Read Write acess for
+ the owner.
- Example:
+5 PAD
+ PAD
- GTM>ZEDIT "/usr/smith/report.txt"
- .
- .
- .
- GTM>WRITE $ZSOURCE
+ PAD=expr Applies to: SD FIFO PIPE
- /usr/smith/report.txt
+ For FIXED format sequential files when the character set is not M, if a
+ multi-byte character (when CHSET is UTF-8) or a surrogate pair (when CHSET
+ is UTF-16) does not fit into the record (either logical as given by WIDTH
+ or physical as given by RECORDSIZE) the WRITE command uses bytes with the
+ value specified by the PAD deviceparameter to fill out the physical
+ record. READ ignores the pad bytes when found at the end of the record.
+ The value for PAD is given as an integer in the range 0-127 (the ASCII
+ characters). PAD is always a byte value and the default is $ZCHAR(32) or
+ [SPACE].
+
+ In UTF-8 mode, there are three cases that cause GT.M to insert PAD
+ characters when WRITEing. When READing GT.M attempts to strip any PAD
+ characters. This stripping only works properly if the RECORDSIZE and PAD
+ are the same for the READ as when the WRITEs occurred. WRITE inserts PAD
+ characters when:
+
+ 1. The file is closed and the last record is less than the RECORDSIZE.
+ Records are padded (for FIXED) by WRITE ! as well as when the file is
+ closed.
+ 2. $X exceeds WIDTH before the RECORDSIZE is full.
+ 3. The next character won't fit in the remaining RECORDSIZE.
+
+ **Note**
+
+ In all UTF-16 character sets, RECORDSIZE must be even and PAD bytes occupy
+ two bytes with the high order byte zero.
Example:
- GTM>ZLINK "BASE.O"
- .
- .
- .
- GTM>WRITE $ZSOURCE
- BASE
+ GTM>do ^padexample
+ padexample
+ zprint ^padexample
+ set a="************"
+ set encoding="UTF-8"
+ set filename="bom"_encoding_".txt"
+ open filename:(newversion:fixed:record=8:pad=66:chset=encoding)
+ use filename
+ write a
+ close filename
+ halt
+ $ cat bomUTF-8.txt
+ **BB**BB**BB**BB**BB**
+ $ od -tcd1 bomUTF-8.txt
+ 0000000 344 270 273 350 246 201 B B 351 233 250 345 234 250 B B
+ -28 -72 -69 -24 -90 -127 66 66 -23 -101 -88 -27 -100 -88 66 66
+ 0000020 350 245 277 347 217 255 B B 347 211 231 345 201 234 B B
+ -24 -91 -65 -25 -113 -83 66 66 -25 -119 -103 -27 -127 -100 66 66
+ 0000040 347 225 231 345 234 250 B B 345 271 263 345 216 237
+ -25 -107 -103 -27 -100 -88 66 66 -27 -71 -77 -27 -114 -97 32 32
+ 0000060
-2 $ZStatus
- $ZStatus
+ In this example, the local variable a is set to a string of three-byte
+ characters. PAD=66 sets padding byte value to $CHAR(66)
- $ZS[TATUS] contains a string value specifying the error condition code and
- location of the last exception condition that occurred during routine
- execution.
+5 PARSE
+ PARSE
- GT.M maintains $ZSTATUS as a string consisting of three or more
- substrings. The string consists of the following:
+ PARSE Applies to: PIPE
- Format: %<FAC>-<SEV>-<ID>, <TEXT>
- Example: %GTM-E-DIVZERO, Attempt to divide by zero
+ The PARSE deviceparameter invokes preliminary validation of the COMMAND
+ value. When debugging, PARSE provides more accessible diagnosis for
+ COMMAND values. By default, OPEN does not validate command values before
+ passing them to the newly created process. PARSE has certain limitations,
+ which may, or may not map to, those of the shell.
- GT.M sets $ZSTATUS when it encounters errors during program execution, but
- not when it encounters errors in a Direct Mode command.
+5 RECORDSIZE
+ RECORDSIZE
- $ZSTATUS is a read-write Intrinsic Special Variable, (i.e., it can occur
- on the left side of the equal sign (=) in the argument to the SET
- command). While it will accept any string, FIS recommends setting it to
- null. M routines cannot modify $ZSTATUS with the NEW command.
+ RECORDSIZE=intexpr Applies to: SD FIFO PIPE
- Example:
+ Overrides the default record size for a disk.
- GTM>WRITE $ZSTATUS
- 150373110,+1^MYFILE,%GTM-E-DIVZERO,
- Attempt to divide by zero
+ If the character set is M, RECORDSIZE specifies the initial WIDTH.
- This example displays the status generated by a divide by zero (0).
+ The RECORDSIZE of a fixed length record for a GT.M sequential disk device
+ is always specified in bytes, rather than characters.
-2 $ZSTep
- $ZSTep
+ For all UTF-16 CHSET values, RECORDSIZE must be even and PAD characters
+ each occupy two bytes in the record.
- $ZST[EP] contains a string value specifying the default action for the
- ZSTEP command. $ZSTEP provides the ZSTEP action only when the ZSTEP
- command does not specify an action.
+ The maximum size of intexpr is 1,048,576 bytes. GT.M produces an error if
+ you specify a value greater than 1,048,576.
- $ZSTEP initially contains the string "B" to enter direct mode. $ZSTEP is a
- read-write Intrinsic Special Variable, (i.e., it can appear on the left
- side of the equal sign (=) in the argument to the SET command).
+ When a Unicode CHSET is in use, GT.M treats RECORDSIZE as a byte limit at
+ which to wrap or truncate output depending on [Z][NO]WRAP. For any Unicode
+ character set, GT.M ignores RECORDSIZE for a device which is already open
+ if any I/O has been done.
- Example:
+ If the character set is not UTF-16, UTF-16LE, UTF-16BE, the default
+ RECORDSIZE is 32K-1bytes.
- GTM>WRITE $ZSTEP
- B
- GTM>
+ If the character set is UTF-16, UTF-16LE or UTF16-BE, the RECORDSIZE must
+ always be in multiples of 2. For these character sets, the default
+ RECORDIZE is 32K-4 bytes.
- This example displays the current value of $ZSTEP, which is the default.
+ For all UTF-16 CHSET values, RECORDSIZE must be even and PAD characters
+ each occupy two bytes in the record.
+
+5 REWIND
+ REWIND
+
+ REWIND Applies to: SD
+
+ REWIND Applies to: Sequential Files
+
+ REWIND positions the file pointer of a sequential disk.
+
+ By default, OPEN does not REWIND.
Example:
- GTM>SET $ZSTEP="ZP @$ZPOS B"
+ OPEN "test40.txt":(REWIND:RECORDSIZE=70:NOWRAP)
- This example sets $ZSTEP to code that displays the contents of the next
- line to execute, and then enters Direct Mode.
+ This example opens file test40.txt and places the file pointer at the
+ beginning of the file.
-2 $ZSYstem
- $ZSYstem
+5 SEEK=strexpr
+ SEEK=strexpr
- $ZSY[STEM] holds the value of the status code for the last subprocess
- invoked with the ZSYSTEM command.
+ SEEK Applies to: SD
-2 $ZTExit
- $ZTExit
+ Positions the current file pointer to the location specified in strexpr.
+ The format of strexpr is a string of the form "[+|-]integer" where
+ unsigned value specifies an offset from the beginning of the file, and an
+ explicitly signed value specifies an offset relative to the current file
+ position. For STREAM or VARIABLE format, the positive intexpr after any
+ sign is a byte offset, while for a FIXED format, it is a record offset. In
+ order to deal with the possible presence of a Byte Order Marker (BOM),
+ SEEK for a FIXED format file written in a UTF character set must follow at
+ least one prior READ since the device was created.
- $ZTE[XIT] contains a string value that controls the GT.M interrupt
- facility at the transaction commit or rollback. At each outermost TCOMMIT
- or TROLLBACK, If +$ZTEXIT evaluates to non-zero (TRUE), then $ZINTERRUPT
- is XECUTEd after completing the commit or rollback.
+ **Note**
- $ZTEXIT is a read-write ISV, that is, it can appear on the left side of
- the equal sign (=) in the argument to the SET command. M routines cannot
- NEW $ZTEXIT. GT.M initializes $ZTEXIT to null at the process startup. Note
- that the changes to the value of $ZTEXIT during a GT.M invocation last for
- the entire duration of the process, so it is the application's
- responsibility to reset $ZTEXIT after $ZINTERRUPT is delivered in order to
- turn off redelivering the interrupt every subsequent transaction commit or
- rollback.
+ If an APPEND is combined with a SEEK deviceparameter the APPEND is done
+ first - regardless of deviceparameter order.
+
+ Example:
+
+ GTM>zprint ^seekdemo
+ seekdemo
+ new x,p
+ set p="seekfixed"
+ open p:(newversion:fixed:recordsize=60)
+ use p
+ ; create file with 9 records of length 60 bytes each
+ ; number from 0 to correspond to record offset
+
+ for i=0:1:8 write $justify(i_" - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-|",60)
+ use p:rewind
+ for i=0:1:8 read x set zk=$zkey use $p write "x= ",x," $zkey= ",zk,! use p
+ close p
+ write !!,"** OPEN with FIXED:RECORDSIZE=60:seek=""5""",!
+ open p:(fixed:recordsize=60:seek="5")
+ use p
+ read x set ZKEY=$zkey
+ ;expect: $ZKEY= 6,0
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ write !,"** use with SEEK=""-3""",!
+ use p:seek="-3"
+ read x set ZKEY=$zkey
+ ;expect: $ZKEY= 4,0
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ write !,"** use with SEEK=""-1"" to read from the same record. read x#20 to read a partial record",!
+ use p:seek="-1"
+ read x#20 set ZKEY=$zkey
+ ;expect: $ZKEY= 3,20
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ write !,"** read x#40 to finish reading the record",!
+ use p
+ read x#40 set ZKEY=$zkey
+ ;expect: $ZKEY= 4,0
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ write !,"** CLOSE NODESTROY and reOPEN with no deviceparameters",!
+ close p:nodestroy
+ open p
+ use p
+ read x set ZKEY=$zkey
+ ;expect: $ZKEY= 5,0
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ write !,"** CLOSE NODESTROY and reOPEN with SEEK=""+2""",!
+ close p:nodestroy
+ open p:seek="+2"
+ use p
+ read x set ZKEY=$zkey
+ ;expect: $ZKEY= 8,0
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ write !,"** CLOSE NODESTROY and reOPEN with M:SEEK=""+3""",!
+ close p:nodestroy
+ open p:(M:seek="+3")
+ use p
+ read x set ZKEY=$zkey
+ ;expect: $ZKEY= 4,0
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ write !,"** CLOSE NODESTROY and reOPEN with APPEND:SEEK=""-1""",!
+ close p:nodestroy
+ open p:(append:seek="-1")
+ use p
+ read x set ZKEY=$zkey
+ ;expect: $ZKEY= 9,0
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ close p
+ write !,"** CLOSE DESTROY and OPEN non-fixed with SEEK=""120"" and read 60 bytes",!
+ open p:seek="120"
+ use p
+ read x#60 set ZKEY=$zkey
+ ;expect: $ZKEY= 180
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ write !,"** CLOSE NODESTROY and reOPEN with append:SEEK=""-60"" and read last 60 bytes",!
+ close p:nodestroy
+ open p:(append:seek="-60")
+ use p
+ read x#60 set ZKEY=$zkey
+ ;expect: $ZKEY= 540
+ use $p write "x= ",x," $zkey= ",ZKEY,!
+ close p
+ quit
- Example:
- ztran.m
- foo;
- set $ztexit=1
- set $zinterrupt="d ^throwint"
- tstart ()
- for i=1:1:10 do
- . set ^ACN(i,"bal")=i*100
- tstart ()
- do ^throwint
- do ^proc
- tcommit:$tlevel=2
- for i=1:1:10 do
- . set ^ACN(i,"int")=i*0.05
- do ^srv
- if $tlevel trollback
- do ^exc
- set $zte="",$zint=""
- quit
- bar;
- write "Begin Transaction",!
- set $zte=1
- tstart ()
- i '$zsigproc($j,$ztrnlnm("sigusrval")) w "interrupt sent...",!!
- for i=1:1:4 set ^B(i)=i*i
- tcommit
- write "End Transaction",!
- do ^srv
- quit
- throwint.m
- thrint
- set $zint="write !,""interrupt occurred at : "",$stack($stack-1,""PLACE""),! set $zte=1"
- if '$zsigproc($j,$ztrnlnm("sigusrval")) write "interrupt sent to process"
- write "***************************************",!!
- quit
- Example:
+ GTM>do ^seekdemo
+ x= 0 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 1,0
+ x= 1 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 2,0
+ x= 2 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 3,0
+ x= 3 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 4,0
+ x= 4 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 5,0
+ x= 5 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 6,0
+ x= 6 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 7,0
+ x= 7 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 8,0
+ x= 8 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 9,0
+
+
+ ** OPEN with FIXED:RECORDSIZE=60:seek="5"
+ x= 5 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 6,0
+
+ ** use with SEEK="-3"
+ x= 3 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 4,0
- GTM>d foo^ztran
- interrupt sent to process
- nterrupt occurred at : thrint+3^throwint
- ***************************************
+ ** use with SEEK="-1" to read from the same record. read x#20 to read a partial record
+ x= 3 - [-05-|-10-|-15-| $zkey= 3,20
- interrupt occurred at : foo+13^ztran
- GTM>
+ ** read x#40 to finish reading the record
+ x= -20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 4,0
- In the above call to foo^ztran, the interrupt handler is a user-defined
- routine, throwint. The process is sent a signal (SIGUSR1), and $ZINTERRUPT
- is executed. At the outermost trollback, the interrupt is rethrown,
- causing $ZINTERRUPT to be executed again.
+ ** CLOSE NODESTROY and reOPEN with no deviceparameters
+ x= 4 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 5,0
- Example:
+ ** CLOSE NODESTROY and reOPEN with SEEK="+2"
+ x= 7 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 8,0
- GTM>w $zint
- IF $ZJOBEXAM()
- GTM>zsy "ls GTM*"
- ls: No match.
+ ** CLOSE NODESTROY and reOPEN with M:SEEK="+3"
+ x= 3 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 4,0
- GTM>d bar^ztran
- Begin Transaction
- interrupt sent...
+ ** CLOSE NODESTROY and reOPEN with APPEND:SEEK="-1"
+ x= 8 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 9,0
- End Transaction
+ ** CLOSE DESTROY and OPEN non-fixed with SEEK="120" and read 60 bytes
+ x= 2 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 180
- GTM>zsy "ls GTM*"
- GTM_JOBEXAM.ZSHOW_DMP_22551_1 GTM_JOBEXAM.ZSHOW_DMP_22551_2
+ ** CLOSE NODESTROY and reOPEN with append:SEEK="-60" and read last 60 bytes
+ x= 8 - [-05-|-10-|-15-|-20-|-25-|-30-|-35-|-40-|-45-|-50-|-55-| $zkey= 540
GTM>
- This uses the default value of $ZINTERRUPT to service interrupts issued to
- the process. The $ZJOBEXAM function executes a ZSHOW "*", and stores the
- output in each GTM_ZJOBEXAM_ZSHOW_DMP for the initial interrupt, and at
- tcommit when the interrupt is rethrown.
+ This program demonstrates the use of the SEEK deviceparameter on OPEN and
+ USE and reOPEN after CLOSE NODESTROY. This test is shown as an M program
+ which may be executed, followed by the expected test output. First the
+ test creates the file called "seekfixed" with 9, 60-byte records and then
+ REWINDs and reads each record and outputs the record followed by $ZKEY
+ which is a record,byte pair. Note that the records are numbered from 0 to
+ match the SEEK record offset. Later in the test the same file is OPENed
+ VARIABLE so $ZKEY will be a byte offset in that case. Details are given
+ after the file output.
+
+ The first OPEN has deviceparameters set to (FIXED:RECORDSIZE=60:SEEK="5")
+ which SEEKs to record offset 5 or physical record 6. Note, FIXED length
+ records and RECORDSIZE remain in effect after a CLOSE NODESTROY unless
+ changed on a reOPEN. Record offset 5 is read and output along with $ZKEY=
+ 6,0 which points to the beginning of record offset 6. Next, a USE with
+ SEEK="-3" is done to move back 3 records to read and output record
+ followed by $ZKEY= 4,0. A USE with SEEK="-1" moves back one record to the
+ beginning of the record just processed. A partial read of 20 bytes is done
+ to show a record offset 3 with a byte offset of 20 or $ZKEY= 3,20. A read
+ of 40 bytes is then done to finish processing that record for a $ZKEY=
+ 4,0. Next a sequence of CLOSE NODESTROY and reOPENs are done. After the
+ first CLOSE NODESTROY a reOPEN is done with no deviceparameters. The state
+ of the file device, including file position, is restored and a read is
+ done of record offset 4 which is output followed by $ZKEY= 5,0. The file
+ device is then CLOSEd NODESTROY and a reOPEN is done with the only
+ deviceparameter being SEEK="+2". The state of the file device is restored
+ and a relative SEEK is done 2 records later in the file with a read which
+ outputs record offset 7 followed by $ZKEY= 8,0. The file device is then
+ CLOSEd NODESTORY and a reOPEN is done with deviceparameters (M:SEEK="+3").
+ The file device is OPENed at the beginning of the file due to the presence
+ of a deviceparameter (M) other than SEEK on reOPEN. A relative SEEK
+ forward of 3 records is then done from the beginning of the file and
+ record offset 3 is read and output followed by $ZKEY= 4,0. The file device
+ is then CLOSEd NODESTORY and a reOPEN is done with the (APPEND:SEEK="-1").
+ APPEND moves the file position to the EOF and then the SEEK="-1" moves the
+ file position to the beginning of record 8 - the final record in the file.
+ Note, the APPEND is applied prior to the SEEK - regardless of
+ deviceparameter order. The file device is then CLOSEd (DESTROY is the
+ default) and OPENed with the only deviceparameter being absolute
+ SEEK="120" to byte offset 120. This processing is NOFIXED by default and a
+ read of x#60 is done and output followed by $ZKEY= 180. The output is the
+ same as record 2 in FIXED format. Finally, the file device is then CLOSEd
+ NODESTROY and a reOPEN is done with deviceparameters (APPEND:SEEK="-60").
+ This will move the file position to the EOF and go back 60 bytes which is
+ the starting offset to the final record in the file. Another read of x#60
+ and is done and output followed by $ZKEY= 540 - which is the size of the
+ file.
-2 $ZTrap
- $ZTrap
+5 SHELL
+ SHELL
- $ZT[RAP] contains a string value that GT.M XECUTEs when an error occurs
- during routine execution.
+ SHELL Applies to: PIPE
- **Note**
+ The SHELL deviceparameter specifies the shell for the new process. By
+ default the newly created process uses the shell specified by the $SHELL
+ environment variable, otherwise, if the environment variable SHELL is
+ undefined the process uses /bin/sh.
- The following discussion assumes that $ETRAP error handling is
- simultaneously not in effect (that is, $ETRAP="").
+5 STDERR
+ STDERR
- When the $ZTRAP variable is not null, GT.M executes $ZTRAP at the current
- level. The $ZTRAP variable has the initial value of "B," and puts the
- process in Direct Mode when an error condition occurs. If the value of
- $ZTRAP is null (""), an exception causes the image to run-down with the
- condition code associated with the exception. If $ZTRAP contains invalid
- source code, GT.M displays an error message and puts the process into
- Direct Mode.
+ STDERR Applies to: PIPE
- $ZTRAP is a read-write Intrinsic Special Variable, (that is, it can appear
- on the left side of the equal sign (=) in the argument to the SET
- command).
+ The STDERR deviceparameter specifies that the stderr output from the
+ created process goes to a PIPE device with the name of the STDERR value.
+ This PIPE device acts as a restricted device that can appear only as the
+ argument to USE, READ and CLOSE commands. It is implicitly READONLY and an
+ attempt to WRITE to it triggers an error. If it has not previously acted
+ as the argument to an explicit CLOSE command, the CLOSE of the PIPE device
+ implicitly closes the the STDERR device.
- $ZTRAP may also appear as an argument to an inclusive NEW command. NEW
- $ZTRAP causes GT.M to set $ZTRAP to null ($ZTRAP="") and to stack the old
- value of $ZTRAP. When the program QUITs from the invocation level where
- the NEW occurred, GT.M restores the value previously stacked by the NEW.
- NEW $ZTRAP provides nesting of $ZTRAP. Because $ZTRAP="" terminates the
- image when an error occurs, SET $ZTRAP= generally follows immediately
- after NEW $ZTRAP. You may use this technique to construct error handling
- strategies corresponding to the nesting of your programs. If the
- environment variable gtm_ztrap_new evaluates to boolean TRUE (case
- insensitive string "TRUE", or case insensitive string "YES", or a non-zero
- number), $ZTRAP is NEWed when $ZTRAP is SET; otherwise $ZTRAP is not
- stacked when it is SET.
+5 STREAM
+ STREAM
- **Note**
+ [NO]STREAM Applies to: SD FIFO PIPE
- QUIT from a $ZTRAP terminates the level at which the $ZTRAP was activated.
+ STREAM and VARIABLE are semantically equivalent unless WRAP is disabled.
+ As long as records do not exceed the WIDTH, they are also equivalent.
- Keep $ZTRAP simple and put complicated logic in another routine. If the
- action specified by $ZTRAP results in another run-time error before
- changing the value of $ZTRAP, GT.M invokes $ZTRAP until it exhausts the
- process stack space, terminating the image. Carefully debug exception
- handling. For more information on error handling, refer "Error
- Processing".
+ When WRAP is disabled and a WRITE exceeds the WIDTH, both truncate the
+ line at the WIDTH, however in STREAM format, each WRITE argument truncates
+ after WIDTH characters regardless of whether the cursor exceeds the WIDTH,
+ while in VARIABLE format, no output ever exceeds the WIDTH.
+
+ While each WRITE argument is truncated if it exceeds the WIDTH, the total
+ record can be of arbitrary length. Note that, for efficiency, the compiler
+ combines sequential literal arguments of a single WRITE into a single
+ string so that the run-time system considers the combined length of the
+ sequence.
+
+ For STREAM or VARIABLE record format files, a READ returns when it
+ encounters an EOL, or has read #length characters for a READ #(fixed
+ length READ), or WIDTH characters if #length is not specified, whichever
+ occurs first.
+
+ By default, records are VARIABLE, NOSTREAM.
Example:
- GTM>S $ZTRAP="ZP @$ZPOS B"
+ set sd="foo.txt"
+ open sd:(newversion:stream)
+ use sd:(width=20:nowrap)
+ for i=1:1:10 write " the quick brown fox jumped over the lazy dog ",$x,!
+ use sd:(rewind:width=100)
+ for i=1:1 use sd read x quit:$zeof use $principal write !,i,?5,x
+ close sd
+ quit
- This example modifies $ZTRAP to display source code for the line where
- GT.M encounters an error before entering Direct Mode.
+ The output of this example is as follows:
+
+ 1 the quick brown fox20
+ 2 the quick brown fox20
+ 3 the quick brown fox20
+ 4 the quick brown fox20
+ 5 the quick brown fox20
+ 6 the quick brown fox20
+ 7 the quick brown fox20
+ 8 the quick brown fox20
+ 9 the quick brown fox20
+ 10 the quick brown fox20
+
+ If you change the FORMAT to VARIABLE, the same example produces the
+ following output.
+
+ 1 the quick brown fox
+ 2 the quick brown fox
+ 3 the quick brown fox
+ 4 the quick brown fox
+ 5 the quick brown fox
+ 6 the quick brown fox
+ 7 the quick brown fox
+ 8 the quick brown fox
+ 9 the quick brown fox
+ 10 the quick brown fox
+
+ If you remove the "!" format from the WRITE sequence for VARIABLE, the
+ same example produces the following output:
+
+ 1 the quick brown fox
+
+ With STREAM, the same example produces the following output:
+
+ 1 the quick brown fox20 the quick brown fox42 the quick brown fox64 the quick brown fox86 the quick b
+ 2 rown fox108 the quick brown fox131 the quick brown fox154 the quick brown fox177 the quick brown fox
+ 3 200 the quick brown fox223
+
+ With STREAM, changing the $X to "abc", the same example produces the
+ following output:
+
+ 1 the quick brown fox the quick brown fox the quick brown fox the quick brown fox the quick brown fox
+ 2 the quick brown fox the quick brown fox the quick brown fox the quick brown fox the quick brown fox
+ 3
- There are four settings of $ZTRAP controlled by the UNIX environment
- variable gtm_ztrap_form.
+ With STREAM, turning the comma between ".. lazy dog" and "abc" into a
+ separate WRITE statement produces:
- The four settings of gtm_ztrap_form are:
+ 1 the quick brown foxabc the quick brown foxabc the quick brown foxabc the quick brown foxabc the qui
+ 2 ck brown foxabc the quick brown foxabc the quick brown foxabc the quick brown foxabc the quick brown
+ 3 foxabc the quick brown foxabc
- * code - If gtm_ztrap_form evaluates to "code" (or a value that is not
- one of the subsequently described values), then GT.M treats $ZTRAP as
- code and handles it as previously described in the documentation.
- * entryref - If gtm_ztrap_form evaluates to "entryref" then GT.M treats
- it as an entryref argument to an implicit GOTO command.
- * adaptive - If gtm_ztrap_form evaluates to "adaptive" then if $ZTRAP
- does not compile to valid M code, then $ZTRAP is treated as just
- described for "entryref." Since there is little ambiguity, code and
- entryref forms of $ZTRAP can be intermixed in the same application.
+5 SYSTEM
+ SYSTEM
- **Important**
+ SYSTEM=expr Applies to: SOC(LOCAL) SD FIFO
- GT.M attempts to compile $ZTRAP before evaluating $ZTRAP as an
- entryref. Because GT.M allows commands without arguments such as QUIT,
- ZGOTO, or HANG as valid labels, be careful not to use such keywords as
- labels for error handling code in "adaptive" mode.
+ This deviceparameter is a synonym for OWNER that is provided in the UNIX
+ version of GT.M for compatibility with OpenVMS applications.
- * pope[ntryref] / popa[daptive] - If gtm_ztrap_form evaluates to
- "POPE[NTRYREF]" or "POPA[DAPTIVE]" (case insensitive) and $ZTRAP value
- is in the form of entryref, GT.M unwinds the M stack from the level at
- which an error occurred to (but not including) the level at which
- $ZTRAP was last SET. Then, GT.M transfers control to the entryref in
- $ZTRAP at the level where the $ZTRAP value was SET. If the UNIX
- environment variable gtm_zyerror is defined to a valid entryref, GT.M
- transfers control to the entryref specified by GTM_ZYERROR (with an
- implicit DO) after unwinding the stack and before transferring control
- to the entyref specified in $ZTRAP.
+ Example:
- **Note**
+ GTM> set perm="rwx"
+ GTM>OPEN "test52.txt":(NEWVERSION:SYSTEM="r":GROUP=perm:WORLD=perm)
+ GTM>ZSYSTEM "ls -la test52.txt"
- Like $ZTRAP values, invocation of device EXCEPTION values follow the
- pattern specified by the current gtm_ztrap_form setting.
+ -r--rwxrwx 1 user group 0 Aug 20 18:36 test52.txt
+ GTM>
-2 $ZUSedstor
- $ZUSedstor
+ This example opens file test52.txt and sets read access for the owner,
+ while others have complete access.
- $ZUSEDSTOR is the value in $ZALLOCSTOR minus storage management overhead
- and represents the actual memory, in bytes, requested by current
- activities. It provides one view (see also $ZALLOCSTOR and $ZREALSTOR) of
- the process memory utilization and can help identify storage related
- problems. GT.M does not permit $ZUSEDSTOR to be SET or NEWed.
+5 TRUNCATE
+ TRUNCATE
-2 $ZVersion
- $ZVersion
+ [NO]TRUNCATE Applies to: SD
- $ZV[ERSION] contains a string value specifying the currently installed
- GT.M. $ZV[ERSION] is a space-delimited string with four pieces described
- as follows:
-
- * The M product name, for example "GT.M".
- * The M product version identifier; the format is: the capital letter
- "V" followed by the major version number, then a period (.), followed
- by the minor version number, then a patch number.
- * The host operating system name and optional version identifier; this
- identifier is only included if different versions of the OS support
- different, compatible versions of the M product.
- * The host hardware designation and optional chipset identifier; this
- identifier is only included if different versions of the hardware
- support different compatible versions of the M product.
+ Truncates the file destroying all data beyond the current file pointer. If
+ APPEND is also specified, the file pointer will be positioned at the end
+ of the file even if TRUNCATE is before APPEND in the list of device
+ parameters.
- M routines cannot modify $ZVERSION.
+ TRUNCATE on a USE $PRINCIPAL command works on a stdout device when the
+ device supports the action.
- Example:
+5 UIC
+ UIC
- GTM>WRITE $ZVERSION
- GT.M V4.3-001B AIX RS6000
+ UIC=expr Applies to: SOC(LOCAL) SD FIFO
- This example displays the current version identifier for GT.M.
+ Specifies the owner and group for the file.
-2 $ZYERror
- $ZYERror
+ Specifies the group that has access to the file. The format of the string
+ is "o,g" where g is a decimal number representing the group portion of the
+ UIC and o is a decimal number representing the owner portion. The
+ super-user can set the file UIC to any value. See the man page for the
+ chown() system call for the rules for regular users since they vary by
+ platform and system configuration.
- $ZYER[ROR] is a read/write ISV that contains a string value pointing to an
- entryref. After GT.M encounters an error, if $ZYERROR is set a non-null
- value, GT.M invokes the routine at the entryref specified by $ZYERROR with
- an implicit DO. It is intended that the code invoked by $ZYERROR use the
- value of $ZSTATUS to select or construct a value to which it SETs $ZERROR.
- If $ZYERROR is not a valid entryref or if an error occurs while executing
- the entryref specified by $ZYERROR, GT.M SETs $ZERROR to the error status
- encountered. GT.M then returns control to the M code specified by
- $ETRAP/$ZTRAP or device EXCEPTION.
+5 VARIABLE
+ VARIABLE
- $ZYERROR is implicitly NEWed on entry to the routine specified by
- $ZYERROR. However, if GT.M fails to compile, GT.M does not transfer
- control to the entryref specified by $ZYERROR.
+ VARIABLE Applies to: SD FIFO PIPE
- GT.M permits $ZYERROR to be modified by the SET and NEW commands.
+ Specifies the VARIABLE record length format for sequential disk files.
-2 Triggers_ISVs
- Triggers ISVs
+ By default, records have variable length format.
- GT.M provides nine ISVs (Intrinsic Special Variables) to facilitate
- trigger operations. With the exception of $ZTWORMHOLE, all numeric
- trigger-related ISVs return zero (0) outside of a trigger context;
- non-numeric ISVs return the empty string.
+5 WORLD
+ WORLD
-3 $ZTDAta
- $ZTDAta
+ WORLD=expr Applies to: SOC(LOCAL) SD FIFO
- Within trigger context, $ZTDATA returns $DATA(@$REFERENCE)#2 for a SET or
- $DATA(@$REFERENCE) for a KILL, ZKILL or ZWITHDRAW prior to the explicit
- update. This provides a fast path alternative, avoiding the need for
- indirection in trigger code, to help trigger code determine the
- characteristics of the triggering node prior to the triggering update. For
- a SET, it shows whether the node did or did not hold data - whether a SET
- is modifying the contents of an existing node or creating data at a new
- node. For a KILL it shows whether the node had descendants and whether it
- had data.
+ WORLD=expr Applies to: LOCAL Sockets, Sequential Files, and FIFO
-3 $ZTLevel
- $ZTLevel
+ Specifies access permissions for users other than the owner who are not in
+ the group specified for a file. This category of users is usually referred
+ to as other in UNIX. The expression is a character string evaluating to
+ null or to any combination of the letters RWX, indicating respectively
+ Read, Write, and eXecute access. When any one of these deviceparameters
+ appear on an OPEN of an existing file, any user category that is not
+ explicitly specified remains unchanged.
- Within trigger context, $ZTLEVEL returns the current level of trigger
- nesting (invocation by a trigger of an additional trigger by an update in
- trigger context).
+ To modify file security, the user who issues the OPEN must have ownership.
- $ZTLEVEL greater than one (>1) indicates that there are nested triggers in
- progress. When a single update invokes multiple triggers solely because of
- multiple trigger matches of that initial (non-trigger) update, they are
- not nested (they are chained) and thus all have same $ZTLEVEL.
+ By default, OPEN and CLOSE do not modify the permissions on an existing
+ file. Unless otherwise specified, when OPEN creates a new file, it
+ establishes security using standard defaulting rules.
Example:
- +^Cycle(1) -commands=Set -xecute="Write ""$ZTLevel for ^Cycle(1) is: "",$ZTLevel Set ^Cycle(2)=1"
- +^Cycle(2) -commands=Set -xecute="Write ""$ZTLevel for ^Cycle(2) is: "",$ZTLevel Set ^Cycle(1)=1"
+ OPEN "test51.txt":(NEWVERSION:WORLD="rw")
- These trigger definitions show different values of $ZTLEVEL when two
- triggers are called recursively (and pathologically).
+ This example opens file test51.txt and specifies Read Write permission for
+ users not in owner's group.
- +^Acct("ID") -commands=set -xecute="set ^Acct(1)=$ztvalue+1"
- +^Acct(sub=:) -command=set -xecute="set ^X($ztvalue)=sub"
+5 WRITEONLY
+ WRITEONLY
- SET ^Acct("ID")=10 invokes both the above triggers in some order and
- $ZTLEVEL will have the same value in both because these triggers are
- chained rather than nested.
+ [NO]WRITEONLY Applies to: PIPE
-3 $ZTNAME
- $ZTNAME
+ The WRITEONLY deviceparameter specifies that the PIPE acts only to send
+ its output to the created process. Any attempt to READ from such a PIPE
+ triggers an error. Note that when you open a PIPE with both STDERR and
+ WRITEONLY you can still READ from the STDERR device.
- Within a trigger context, $ZTNAME returns the trigger name. Outside a
- trigger context, $ZTNAME returns an empty string.
+5 ZBFSIZE
+ ZBFSIZE
-3 $ZTOLdval
- $ZTOLdval
+ ZBFSIZE Applies to: SOC
- Within trigger context, $ZTOLDVAL returns the prior (old) value of the
- global node whose update caused the trigger invocation. This provides a
- fast path alternative to $GET(@$REFERENCE) at trigger entry (which avoids
- the heavyweight indirection ). If there are multiple triggers matching the
- same node (chained), $ZTOLDVAL returns the same result for each of them.
+ Allocates a buffer used by GT.M when reading from a socket. The ZBFSIZE
+ deviceparameter should be at least as big as the largest message expected.
+
+ By default, the size of ZBFSIZE is 1024 and the maximum it can be is
+ 1048576.
+
+5 ZDELAY
+ ZDELAY
+
+ Z[NO]DELAY Applies to: SOC(TCP)
+
+ Controls buffering of data packets by the system TCP stack using the
+ TCP_NODELAY option to the setsockopt system call. This behavior is
+ sometimes known as the Nagle algorithm. The default is ZDELAY. This delays
+ sending additional packets until either an acknowledgment of previous
+ packets is received or an interval passes. If several packets are sent
+ from one end of a connection before the other end responds, setting
+ ZNODELAY may be desirable though at the cost of additional packets being
+ transmitted over the network. ZNODELAY must be fully spelled out.
+
+ LOCAL sockets ignore the ZDELAY deviceparameter.
Example:
- +^Acct(1,"ID") -commands=Set -xecute="Write:$ZTOLdval ""The prior value of ^Acct(1,ID) was: "",$ZTOLdval"
+ open tcpdev:(LISTEN=portno_":TCP":attach="server":zbfsize=2048:zibfsize=1024):timeout:"SOCKET"
- This trigger gets invoked with a SET and displays the prior value (if it
- exists) of ^Acct(1,"ID").
+ This example opens the socket device tcpdev and allocates a buffer size of
+ 2048 bytes.
- GTM>w ^Acct(1,"ID")
- 1975
- GTM>s ^Acct(1,"ID")=2011
- The prior value of ^Acct(1,ID) was: 1975
+5 ZFF
+ ZFF
-3 $ZTRIggerop
- $ZTRIggerop
+ Z[NO]FF=expr Applied to: SOC
- Within trigger context, for SET (including MERGE and $INCREMENT()
- operations), $ZTRIGGEROP has the value "S". For KILL, $ZTRIGGEROP has the
- value "K" For ZKILL or ZWITHDRAW, $ZTRIGGEROP has the value "ZK".
+ Z[NO]FF=expr Applies to: Socket Device
-3 $ZTSlate
- $ZTSlate
+ expr specifies a string of characters, typically in $CHAR() format to send
+ to socket device, whenever a routine issues a WRITE #. When no string is
+ specified or when ZFF="", then no characters are sent. The default in GT.M
+ is ZNOFF.
- $ZTSLATE allows you to specify a string that you want to make available in
- chained or nested triggers invoked for an outermost transaction (when a
- TSTART takes $TLEVEL from 0 to 1). You might use $ZTSLATE to accumulate
- transaction-related information, for example $ZTOLDVAL and $ZTVALUE,
- available within trigger context for use in a subsequent trigger later in
- the same transaction. For example, you can use $ZTSLATE to build up an
- application history or journal record to be written when a transaction is
- about to commit.
+5 ZIBFSIZE
+ ZIBFSIZE
- You can SET $ZTSLATE only while a database trigger is active. GT.M clears
- $ZTSLATE for the outermost transaction or on a TRESTART. However, GT.M
- retains $ZTSLATE for all sub-transactions (where $TLEVEL>1).
+ ZIBFSIZE Applies to: SOC(TCP)
+
+ ZIBFSIZE Applies to: Socket Device(TCP)
+
+ Allocates a buffer used by GT.M when reading from a socket. The ZBFSIZE
+ deviceparameter should be at least as big as the largest message expected.
+
+ By default, the size of ZBFSIZE is 1024 and the maximum it can be is
+ 1048576.
+
+ Note that LOCAL sockets ignore the ZIBFSIZE deviceparameter.
+
+4 OPEN_Deviceparameter_Table
+ OPEN Deviceparameter Table
+
+ +------------------------------------------------------------+
+ | OPEN Deviceparameters |
+ |------------------------------------------------------------|
+ | OPEN DEVICEPARAMETER | TRM | SD | FIFO | PIPE | NULL | SOC |
+ |------------------------------------------------------------|
+ | TRM: Valid for terminals and printers |
+ | |
+ | SD: Valid for sequential disk files |
+ | |
+ | FIFO: Valid for FIFOs |
+ | |
+ | NULL: Valid for null devices |
+ | |
+ | PIPE: Valid for PIPEs |
+ | |
+ | SOC: Valid for Socket devices |
+ |------------------------------------------------------------|
+ | APPEND | | X | | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | ATTACH=expr | | | | | | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | CHSET=encoding | X | X | X | X | X | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | COMMAND=expr | | | | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | CONNECT=expr | | | | | | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]DELIMITER | | | | | | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]EMPT[ERM] | X | | | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | EXCEPTION=expr | X | X | X | | X | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | FIFO | | | X | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]FIXED | | X | X | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]FOLLOW | | X | | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | GROUP=expr | | X | X | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | KEY | | X | X | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | IKEY | | X | X | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | ICHSET=encoding | X | X | X | X | X | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | INDEPENDENT | | | | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | IOERROR=expr | | | | | | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]NEWVERSION | | X | X | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | OCHSET=encoding | X | X | X | X | X | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | OKEY | | X | X | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | OWNER=expr | | X | X | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | PARSE | | | | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]READONLY | | X | X | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | RECORDSIZE=intexpr | | X | X | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | SEEK=strexpr | | X | | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | SHELL=expr | | | | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | STDERR=expr | | | | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]STREAM | | X | | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | SYSTEM=expr | | X | X | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]TRUNCATE | | X | X | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | UIC=expr | | X | X | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | VARIABLE | | X | X | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | WORLD=expr | | X | X | | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | [NO]WRITEONLY | | | | X | | |
+ |----------------------+-----+----+------+------+------+-----|
+ | [Z][NO]WRAP | X | X | X | X | X | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | ZBFSIZE | | | | | | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | Z[NO]DELAY | | | | | | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | Z[NO]FF | | | | | | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | ZIBFSIZE | | | | | | X |
+ |----------------------+-----+----+------+------+------+-----|
+ | LISTEN=expr | | | | | | X |
+ +------------------------------------------------------------+
- Example:
+3 Use
+ Use
- TSTART () ; Implicitly clears $ZTSLAT
- SET ^ACC(ACN1,BAL)=AMT ; Trigger sets $ZTSLATE=ACN_"|"
- SET ^ACC(ACN2,BAL)=-AMT ; Trigger sets $ZTSLATE=$ZTSLATE_ACN_"|"
- ZTRIGGER ^ACT("TRANS") ; Trigger uses $ZTSLATE to update transaction log
- TCOMMIT
+ The USE command selects the current device for READs (input) and WRITEs
+ (output).
-3 $ZTUPdate
- $ZTUPdate
+ The format of the USE command is:
- Within trigger context, for SET commands where the GT.M trigger specifies
- a piece separator, $ZTUPDATE provides a comma separated list of piece
- numbers of pieces that differ between the current values of $ZTOLDVAL and
- $ZTVALUE. If the trigger specifies a piece separator, but does not specify
- any pieces of interest, $ZTUPDATE identifies all changed pieces. $ZTUPDATE
- is 0 in all other cases (that is: for SET commands where the GT.M trigger
- does not specify a piece separator or for KILLs). Note that if an update
- matches more than one trigger, all matching triggers see the same
- $ZTOLDVAL at trigger entry but potentially different values of $ZTVALUE so
- $ZTUPDATE could change due to the actions of each matching trigger even
- though all matching triggers have identical -[z]delim and -piece
- specifications.
+ U[SE][:tvexpr] expr[:(keyword[=expr][:...])][,...]
Example:
- +^trigvn -commands=Set -pieces=1;3:6 -delim="|" -xecute="Write !,$ZTUPDATE"
-
- In the above trigger definition entry, $ZTUPDATE displays a comma
- separated list of the changed piece numbers if on of the pieces of
- interest: 1,3,4,5,or 6 are modified by the update.
-
- GTM>write ^trigvn
- Window|Table|Chair|Curtain|Cushion|Air Conditioner
- GTM>set ^trigvn="Window|Dining Table|Chair|Vignette|Pillow|Air Conditioner"
- 4,5
-
- Note that even though piece numbers 2,4 and 5 are changed, $ZTUPDATE
- displays only 4,5 because the trigger is not defined for updates for the
- second piece.
-
-3 $ZTVAlue
- $ZTVAlue
-
- For SET, $ZTVALUE has the value assigned to the node by the explicit SET
- operation. Modifying $ZTVALUE within a trigger modifies the eventual value
- GT.M assigns to the node. Note that changing $ZTVALUE has a small
- performance impact because it causes an additional update operation on the
- node once all trigger code completes. If a node has multiple associated
- triggers each trigger receives the current value of $ZTVALUE, however,
- because the triggers run in arbitrary order, FIS strongly recommends no
- more than one trigger change any given element of application data, for
- example, a particular piece. For KILL and its variants, $ZTVALUE returns
- the empty string. While GT.M accepts updates to $ZTVALUE within the
- trigger code invoked for a KILL or any of its variants, it ultimately
- discards any such value. Outside trigger context, attempting to SET
- $ZTVALUE produces a SETINTRIGONLY error.
-
-3 $ZTWOrmhole
- $ZTWOrmhole
+ USE $P:(X=0:Y=$Y-1:NOECHO)
- $ZTWORMHOLE allows you to specify a string up to 128KB of information you
- want to make available during trigger execution. You can use $ZTWORMHOLE
- to supply an application-context or process context to your trigger logic.
- Because GT.M makes $ZTWORMHOLE available throughout the duration of the
- process, you can access or update $ZTWORMHOLE both from inside and outside
- a trigger.
+ This example USEs the principal device. If that device is a terminal, the
+ deviceparameters turn off echo and position the cursor to the beginning of
+ the previous line.
- $ZTWORMHOLE provides a mechanism to access information from a
- process/application context that is otherwise unavailable in trigger
- context. GT.M records any non-empty string value of $ZTWORMHOLE in the
- GT.M database journal file as part of any update that invokes at least one
- trigger which references $ZTWORMHOLE. GT.M also transmits any non-NULL
- $ZTWORMHOLE value in the replication stream, thus providing the same
- context to triggers invoked by MUPIP processes (either as part of the
- replicating instance update process or as part of MUPIP journal
- recovery/rollback). Therefore, whenever you use $ZTWORMHOLE in a trigger,
- you create something like a wormhole for process context that is otherwise
- NEWed in the run-time or non-existent in MUPIP.
+4 USE_Deviceparameters
+ USE Deviceparameters
- Note that if trigger code does not reference $ZTMORMHOLE, GT.M does not
- make it available to MUPIP (via the journal files or replication stream).
- Therefore, if a replicating secondary has different trigger code than the
- initiating primary (an unusual configuration) and the triggers on the
- replicating node require information from $ZTWORMHOLE, the triggers on the
- initiating node must reference $ZTWORMHOLE to ensure GT.M maintains the
- data it contains for use by the update process on the replicating node.
- While you can change $ZTWORMHOLE within trigger code, because of the
- arbitrary ordering of triggers on the same node, such an approach requires
- careful design and implementation. GTM allows $ZTWORMHOLE to be NEW'd.
- NEWing $ZTWORMHOLE is slightly different from NEWing other ISVs/variables
- in the sense that the former retains its original value whereas the latter
- does not. However, like other NEWs, GT.M restores $ZTWORMHOLE's value when
- the stack level pops.
+5 ATTACH
+ ATTACH
- The following table summarizes the read/write permissions assigned to all
- trigger-related ISVs within trigger context and outside trigger context.
+ ATTACH=expr Applies to: Socket Device
- +------------------------------------------------------------------------+
- | Intrinsic Special | Within Trigger | Notes |
- | Variable | Context | |
- |-------------------+----------------+-----------------------------------|
- | | | Set to gtm_trigger_etrap or the |
- | $ETRAP | Read / Write | empty string when entering |
- | | | trigger context. |
- |-------------------+----------------+-----------------------------------|
- | $REFERENCE | Read only | Restored at the completion of a |
- | | | trigger. |
- |-------------------+----------------+-----------------------------------|
- | $TEST | Read only | Restored at the completion of a |
- | | | trigger. |
- |-------------------+----------------+-----------------------------------|
- | | | Always >=1 in trigger code; must |
- | $TLEVEL | Read only | be the same as the completion of |
- | | | processing a trigger as it was at |
- | | | the start. |
- |-------------------+----------------+-----------------------------------|
- | $ZTNAME | Read only | Returns the trigger name. |
- |-------------------+----------------+-----------------------------------|
- | $ZTDATA | Read only | Shows prior state. |
- |-------------------+----------------+-----------------------------------|
- | $ZTLEVEL | Read only | Shows trigger nesting. |
- |-------------------+----------------+-----------------------------------|
- | $ZTOLDVAL | Read only | Shows the pre-update value. |
- |-------------------+----------------+-----------------------------------|
- | $ZTRAP | Read only - "" | Must use $ETRAP in trigger code. |
- |-------------------+----------------+-----------------------------------|
- | $ZTRIGGEROP | Read only | Shows the triggering command. |
- |-------------------+----------------+-----------------------------------|
- | $ZTUPDATE | Read only | Lists modified pieces (if |
- | | | requested) for SET. |
- |-------------------+----------------+-----------------------------------|
- | $ZTVALUE | Read / Write | Can change the eventual applied |
- | | | value for SET. |
- |-------------------+----------------+-----------------------------------|
- | | | Holds application context because |
- | $ZTWORMHOLE | Read / Write | trigger code has no access to the |
- | | | local variable context. |
- |-------------------+----------------+-----------------------------------|
- | | | Holds outermost transaction |
- | $ZTSLATE | Read/ Write | context for chained or nested |
- | | | triggers. |
- +------------------------------------------------------------------------+
+ expr specifies the handle for a socket in the socketpool. ATTACH looks up
+ expr in the socketpool's collection of sockets and brings the one found to
+ the current SOCKET device. If an ATTACH operation is successful, the
+ attached socket becomes the current socket for the device.
-1 IO_Processing
- IO Processing
+ ATTACH is not compatible with any other device parameters in the USE
+ command.A socket can move from one device to another using DETACH/ATTACH.
- This chapter describes the following topics which relate to input and
- output processing:
+ **Note**
- * Input/Output Intrinsic Special Variables, and their Maintenance.
+ A socket does not carry I[O]CHSET with it while being moved. Such a socket
+ uses the I[O]CHSET of the device it is ATTACHed to. If there is input
+ still buffered, this may cause unintentional consequences in the
+ application if I[O]CHSET changes. GT.M does not detect (or report) a
+ change in I[O]CHSET due to DETACH/ATTACH.
- GT.M provides several intrinsic special variables that allow processes
- to examine, and in some cases change, certain aspects of the
- input/output (I/O) processing. The focus in this chapter is how GT.M
- handles the standard ones, such as $IO, $X, $Y, and those that are
- GT.M-specific (for example, $ZA, $ZB).
+5 CANONICAL
+ CANONICAL
- * Input/Output Devices
+ [NO]CANONICAL Applies to: TRM
- Each device type supported by GT.M responds to a particular subset of
- deviceparameters, while ignoring others. Devices may be programmed in
- a device-specific manner, or in a device-independent manner. This
- chapter discusses each device type, and provides tables of their
- deviceparameters.
+ [NO]CANONICAL Applies to: Terminals and Printers
- * Input/Output Commands and their Deviceparameters
+ Enables or disables canonical input as controlled by the ICANON terminal
+ attribute. See the documentation on your platform for details, but in
+ general this would be erase and kill edit functions, and lines delimited
+ by NL (usually <LF>), EOF (usually ^D), and EOL (usually not defined).
- GT.M bases its I/O processing on a simple character stream model. GT.M
- does not use any pre-declared formats. This chapter describes the GT.M
- I/O commands OPEN, USE, READ, WRITE, and CLOSE.
+ By default, canonical input is enabled (that is [NO]CANONICAL is the
+ default).
- OPEN, USE, and CLOSE commands accept deviceparameters, which are keywords
- that permit a GT.M program to control the device state. Some
- deviceparameters require arguments. The current ANSI standard for GT.M
- does not define the deviceparameters for all devices. This chapter
- includes descriptions of the GT.M deviceparameters in the sections
- describing each command.
+5 CENABLE
+ CENABLE
-2 Using_Terminals
- Using Terminals
+ [NO]CENABLE Applies to: Terminals and Printers
- A GT.M process assigns $PRINCIPAL to the UNIX standard input of the
- process (for READ) and standard output (for WRITE). For a local
- interactive process, $PRINCIPAL identifies the "terminal" from which the
- user is signed on.
+ Enables or disables the ability to force GT.M into Direct Mode by entering
+ <CTRL-C> at $PRINCIPAL.
- While all terminals support the CTRAP deviceparameter, only $PRINCIPAL
- supports CENABLE. While CTRAP allows terminal input to redirect program
- flow, CENABLE allows the terminal user to invoke the Direct Mode.
+ If CENABLE is set, <CTRL-C> interrupts process execution.
- Directly connected printers often appear to GT.M as a terminal (although
- printers generally do not provide input) regardless of whether the printer
- is connected to the computer with a high speed parallel interface, or an
- asynchronous terminal controller.
+ By default, CENABLE is set. If CTRAP contains $C(3), CENABLE is disabled.
-3 Set_Characteristics
- Set Characteristics
+ Example:
- GT.M does not isolate its handling of terminal characteristics from the
- operating system environment at large. GT.M inherits the operating system
- terminal characteristics in effect at the time the GT.M image is invoked.
- When GT.M exits, the terminal characteristics known by the operating
- system are restored.
+ use $principal:(nocenable:ctrap="":exception="")
- However, if the process temporarily leaves the GT.M environment with a
- ZSYSTEM command , GT.M does not recognize any changes to the terminal
- characteristics left by the external environment. This may cause
- disparities between the physical behavior of the terminal, and the
- perceived behavior by GT.M.
+5 CLEARSCREEN
+ CLEARSCREEN
- UNIX enforces standard device security for explicit OPENs of terminals
- other than the sign-in terminal ($PRINCIPAL). If you are unable to OPEN a
- terminal, contact your system manager.
+ CLEARSCREEN Applies to: TRM
- USE of a terminal causes the device driver to flush the output buffer.
- This feature of the USE command provides routine control over the timing
- of output, which is occasionally required. However, it also means that
- redundant USE commands may induce an unnecessary performance penalty.
- Therefore, FIS recommends restricting USE commands to redirecting I/O,
- modifying deviceparameters, and initiating specifically required flushes.
+ CLEARSCREEN Applies to: Terminals and Printers
- The terminal input buffer size is fixed at 1024 on UNIX and a variable
- read terminates after 1023 characters.
+ Clears the terminal screen from the present cursor position to the bottom
+ of the screen. The CLEARSCREEN deviceparameter does not change the cursor
+ position or the $X and $Y variables.
-4 Set_TERM
- Set TERM
+ Example:
- The environment variable $TERM must specify a terminfo entry that
- accurately matches the terminal (or terminal emulator) settings. Refer to
- the terminfo man pages for more information on the terminal settings of
- the platform where GT.M needs to run.
+ U $P:(X=0:Y=0:CLEAR)
- Some terminfo entries may seem to work properly but fail to recognize
- function key sequences or position the cursor properly in response to
- escape sequences from GT.M. GT.M itself does not have any knowledge of
- specific terminal control characteristics. Therefore, it is important to
- specify the right terminfo entry to let GT.M communicate correctly with
- the terminal. You may need to add new terminfo entries depending on their
- specific platform and implementation. The terminal (emulator) vendor may
- also be able to help.
+ This example positions the cursor to "home" in the upper left corner of a
+ VDT and clears the entire current screen "page."
- GT.M uses the following terminfo capabilities. The full variable name is
- followed by the capname in parenthesis:
+5 CONNECT
+ CONNECT
- auto_right_margin(am), clr_eos(ed), clr_eol(el), columns(cols), cursor_address(cup), cursor_down(cud1),cursor_left(cub1), cursor_right(cuf1), cursor_up(cuu1), eat_newline_glitch(xenl), key_backspace(kbs), key_dc(kdch1),key_down(kcud1), key_left(kcub1), key_right(kcuf1), key_up(kcuu1), key_insert(kich1), keypad_local(rmkx),keypad_xmit(smkx), lines(lines).
+ CONNECT=expr Applies to: SOC
- GT.M sends keypad_xmit before terminal reads for direct mode and READs
- (other than READ *) if EDITING is enabled. GT.M sends keypad_local after
- these terminal reads.
+ CONNECT=expr Applies to: Socket Device
-3 Summary
- Summary
+ Enables a client connection with a server, which is located by the
+ information provided by expr. A new socket is allocated for the client
+ connection and is made the current socket for the device, if the operation
+ is successful.
- The following tables provide a brief summary of deviceparameters for
- terminals, grouped into related areas.
+ expr specifies the protocol and the protocol-specific information.
+ Currently, GT.M supports TCP/IP and LOCAL (also known as UNIX domain)
+ socket protocols.
- +----------------------------------------------------------------------+
- | Error Processing Deviceparameters |
- |----------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-----------------+---------+------------------------------------------|
- | EXCEPTION=expr | O/U/C | Controls device-specific error handling. |
- +----------------------------------------------------------------------+
+ For more information, refer to "CONNECT".
- +------------------------------------------------------------------------+
- | Interaction Management Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-----------------------+---------+--------------------------------------|
- | | | Controls whether <CTRL-C> on |
- | [NO]CENABLE | U | $PRINCIPAL causes GT.M to go to |
- | | | direct mode. |
- |-----------------------+---------+--------------------------------------|
- | CTRAP=expr | U | Controls vectoring on trapped <CTRL> |
- | | | characters. |
- |-----------------------+---------+--------------------------------------|
- | [NO]ESCAPE | U | Controls escape sequence processing. |
- |-----------------------+---------+--------------------------------------|
- | | | Controls interpretation by the |
- | [NO]PASTHRU | U | operating system of special control |
- | | | characters (for example <CTRL-B>). |
- |-----------------------+---------+--------------------------------------|
- | [NO]TERMINATOR[=expr] | U | Controls characters that end a READ |
- +------------------------------------------------------------------------+
+ **Note**
- +------------------------------------------------------------------+
- | Flow Control Deviceparameters |
- |------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-----------------+---------+--------------------------------------|
- | [NO]CONVERT | U | Controls forcing input to uppercase. |
- |-----------------+---------+--------------------------------------|
- | [NO]FILTER | U | Controls some $X, $Y maintenance. |
- |-----------------+---------+--------------------------------------|
- | FLUSH | U | Clears the typeahead buffer. |
- |-----------------+---------+--------------------------------------|
- | [NO]HOSTSYNC | U | Controls host's use of XON/XOFF. |
- |-----------------+---------+--------------------------------------|
- | [NO]READSYNC | U | Controls wrapping READs in XON/XOFF. |
- |-----------------+---------+--------------------------------------|
- | [NO]TTSYNC | U | Controls input response to XON/XOFF. |
- |-----------------+---------+--------------------------------------|
- | [NO]TYPEAHEAD | U | Controls unsolicited input handling. |
- +------------------------------------------------------------------+
+ CONNECT is not compatible with LISTEN.
- +------------------------------------------------------------------------+
- | Screen Management Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-------------------+---------+------------------------------------------|
- | CLEARSCREEN | U | Clears from cursor to end-of-screen. |
- |-------------------+---------+------------------------------------------|
- | DOWNSCROLL | U | Moves display down one line. |
- |-------------------+---------+------------------------------------------|
- | [NO]ECHO | U | Controls the host echo of input. |
- |-------------------+---------+------------------------------------------|
- | ERASELINE | U | Clears from cursor to end-of-line. |
- |-------------------+---------+------------------------------------------|
- | [Z]LENGTH=intexpr | U | Controls maximum number of lines on a |
- | | | page ($Y). |
- |-------------------+---------+------------------------------------------|
- | UPSCROLL | U | Moves display up one line. |
- |-------------------+---------+------------------------------------------|
- | [Z]WIDTH=intexpr | U | Controls the maximum width of an output |
- | | | line ($X). |
- |-------------------+---------+------------------------------------------|
- | [Z][NO]WRAP | U | Controls handling of output lines longer |
- | | | than the maximum width. |
- |-------------------+---------+------------------------------------------|
- | X=intexpr | U | Positions the cursor to column intexpr. |
- |-------------------+---------+------------------------------------------|
- | Y=intexpr | U | Positions the cursor to row intexpr. |
- +------------------------------------------------------------------------+
+ Although CONNECT can be used with USE command, FIS recommends not to use
+ it that way, because unlike the OPEN command, there is no way to specify a
+ timeout to the USE command. CONNECT in the USE command take a default
+ timeout value of 0.
- O: Applies to the OPEN command
+5 CONVERT
+ CONVERT
- U: Applies to the USE command
+ [NO]CONVERT Applies to: TRM
- C: Applies to the CLOSE command
+ [NO]CONVERT Applies to: Terminals and Printers
-2 _Sequential_Files
- Sequential Files
+ Enables or disables GT.M from converting lowercase input to uppercase
+ during READs.
- GT.M provides access to sequential files. These files allow linear access
- to records. Sequential files are used to create programs, store reports,
- and to communicate with facilities outside of GT.M.
+ By default, the terminal device driver operates NOCONVERT.
-3 Sequential_File_Pointers
- Sequential File Pointers
+ Example:
- Sequential file I/O operations use a construct called a file pointer. The
- file pointer logically identifies the next record to read or write. OPEN
- commands position the file pointer at the beginning of the file (REWIND)
- or at the end-of-file (APPEND). APPEND cannot reposition a file currently
- open. Because the position of each record depends on the previous record,
- a WRITE destroys the ability to reliably position the file pointer to
- subsequent records in a file. Therefore, by default (NOTRUNCATE), GT.M
- permits WRITEs only when the file pointer is positioned at the end of the
- file.
+ use $principal:(convert)
+ READ X
- A file that has been previously created and contains data that should be
- retained can also be opened with the device parameter APPEND.
+ This example converts all lowercase to uppercase during READ X.
- If a device has TRUNCATE enabled, a WRITE issued when the file pointer is
- not at the end of the file causes all contents after the current file
- pointer to be discarded. This effectively moves the end of the file to the
- current position and permits the WRITE.
+5 CTRAP
+ CTRAP
-3 Line_Terminators
- Line Terminators
+ CTRAP=expr Applies to: TRM
- LF ($CHAR(10)) terminates the logical record for all M mode sequential
- files, TRM, PIPE, and FIFO. For non FIXED format sequential files and
- terminal devices for which character set is not M, all the standard
- Unicode line terminators terminate the logical record. These are U+000A
- (LF), U+0000D (CR), U+000D followed by U+000A (CRLF), U+0085 (NEL), U+000C
- (FF), U+2028 (LS) and U+2029 (PS).
+ CTRAP=expr Applies to: Terminals and Printers
-3 _Binary_Files
- Binary Files
+ Establishes the <CTRL> characters in the expression as trap characters for
+ the current device. When GT.M receives a trap character in the input from
+ a device, GT.M issues a run-time exception. The device does not have to be
+ the current device, that is $IO.
- To write a binary data file, open it with FIXED:WRAP:CHSET="M" and set $X
- to zero before the WRITE to avoid filling the last record with spaces (the
- default PAD byte value).
+ The <CTRL> characters are ASCII 0 though 31.
- **Note**
+ For example, the command U $P:CTRAP=$C(26,30,7,19) sets a trap for the
+ ASCII characters <SUB>, <RS>, <BEL> and <DC3>.
- With CHSET not "M", FIXED has a different definition. Each record is
- really the same number of bytes as specified by RECORDSIZE. Padding bytes
- are added as needed to each record.
+ Specifying CTRAP completely replaces the previous CTRAP list. Setting
+ CTRAP to the null string ("") disables character trapping.
- Example:
+ A trap character enabled by CTRAP produces one of the following actions:
- GTM>zprint ^gtmcp
- gtmcp ; Copy a file using GT.M
- new dest,line,max,src
- if 2>$length($zcmdline," ") write "Usage: $gtm_dist/mumps -run gtmcp srcfile destfile",!
- set dest=$piece($zcmdline," ",2)
- set src=$piece($zcmdline," ",1)
- set max=1024*1024
- open src:(readonly:fixed:wrap:chset="M")
- open dest:(newversion:fixed:wrap:chset="M")
- for k line use src read line#max quit:$zeof do
- . use $principal write $length(line),!
- . use dest write line set $x=0
- use $principal
- if $length(line) use dest write line s $x=0 use $principal
- close src
- close dest
- quit
+ For more information on error handling, refer to Chapter 13: "Err
+ Processing".
-3 Summary
- Summary
+ When CTRAP includes <CTRL-C>, [NO]CENABLE has no effect. CTRAPping
+ <CTRL-C> also takes precedence over CENABLE.
- The following tables provide a brief summary of deviceparameters for
- sequential files grouped into related areas.
+5 DELIMITER
+ DELIMITER
- +----------------------------------------------------------------------+
- | Error Processing Deviceparameters |
- |----------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-----------------+---------+------------------------------------------|
- | EXCEPTION=expr | O/U/C | Controls device-specific error handling. |
- +----------------------------------------------------------------------+
+ [NO]DELIMITER Applies to: SOC
- +------------------------------------------------------------------------+
- | File Pointer Positioning Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-----------------+---------+--------------------------------------------|
- | APPEND | O | Positions file pointer at EOF. |
- |-----------------+---------+--------------------------------------------|
- | REWIND | O/U/C | Positions file pointer at start of the |
- | | | file. |
- +------------------------------------------------------------------------+
+ [NO]DELIMITER Applies to: Socket Device
- +------------------------------------------------------------------------+
- | File Format Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETERS | COMMAND | COMMENT |
- |--------------------+---------+-----------------------------------------|
- | [NO]FIXED | O | Controls whether records have fixed |
- | | | length. |
- |--------------------+---------+-----------------------------------------|
- | [Z]LENGTH=intexpr | U | Controls virtual page length. |
- |--------------------+---------+-----------------------------------------|
- | RECORDSIZE=intexpr | O | Specifies maximum record size. |
- |--------------------+---------+-----------------------------------------|
- | STREAM | O | Specifies the STREAM format. |
- |--------------------+---------+-----------------------------------------|
- | VARIABLE | O | Controls whether records have variable |
- | | | length. |
- |--------------------+---------+-----------------------------------------|
- | [Z]WIDTH=intexpr | U | Controls maximum width of an output |
- | | | line. |
- |--------------------+---------+-----------------------------------------|
- | [Z][NO]WRAP | O/U | Controls handling of records longer |
- | | | than device width. |
- +------------------------------------------------------------------------+
+ DELIMITER establishes or replaces the list of delimiters used by the
+ current socket. The default is NODELIMITER.
- +------------------------------------------------------------------------+
- | File Access Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-----------------+---------+--------------------------------------------|
- | DELETE | C | Specifies file be deleted by CLOSE. |
- |-----------------+---------+--------------------------------------------|
- | GROUP=expr | O/C | Specifies file permissions for other users |
- | | | in the owner's group. |
- |-----------------+---------+--------------------------------------------|
- | NEWVERSION | O | Specifies GT.M create a new version of |
- | | | file. |
- |-----------------+---------+--------------------------------------------|
- | OWNER=expr | O/C | Specifies file permissions for the owner |
- | | | of file. |
- |-----------------+---------+--------------------------------------------|
- | [NO]READONLY | O | Controls read-only file access. |
- |-----------------+---------+--------------------------------------------|
- | RENAME=expr | C | Specifies CLOSE replace name of a disk |
- | | | file with name specified by expression. |
- |-----------------+---------+--------------------------------------------|
- | SYSTEM=expr | O/C | Specifies file permissions for the owner |
- | | | of the file (same as OWNER). |
- |-----------------+---------+--------------------------------------------|
- | [NO]TRUNCATE | O/U | Controls overwriting of existing data in |
- | | | file. |
- |-----------------+---------+--------------------------------------------|
- | UIC=expr | O/C | Specifies file's owner ID. |
- |-----------------+---------+--------------------------------------------|
- | WORLD=expr | O/C | Specifies file permissions for users not |
- | | | in the owner's group. |
- +------------------------------------------------------------------------+
+ expr must be a string of the following format:
- O: Applies to the OPEN command
+ 1. ':' is used to separate delimiters (it is the delimiter for
+ delimiters).
+ 2. '/' serves as an escape character.
- U: Applies to the USE command
+ **Note**
- C: Applies to the CLOSE command
+ expr "ab:/:://:bc" is interpreted as four delimiters, which are "ab", ":",
+ "/", and "bc". One socket can have 0-64 delimiters and each delimiter can
+ contain 1-64 characters.
-2 _FIFO_Characteristics
- FIFO Characteristics
+ Example:
- FIFOs have most of the same characteristics as other sequential files,
- except that READs and WRITEs can occur in any order.
+ See "Socket (server.m)" example.
- The following characteristics of FIFO behavior may be helpful in using
- them effectively.
+5 DETACH
+ DETACH
- With READ:
+ DETACH=expr Applies to: SOC
- * If a READ is done while there is no data in the FIFO:
+ DETACH=expr Applies to: Socket Device
- The process hangs until data is put into the FIFO by another process, or
- the READ times out, when a timeout is specified.
+ Removes the socket identified by expr from the current socket device,
+ without affecting any existing connection of that socket. The removed
+ socket is placed in the socketpool and may be attached to another socket
+ device. If the socket being removed is the current socket, then GT.M does
+ the following:
- The following table shows the result and the values of I/O status
- variables for different types of READ operations on a FIFO device.
+ **Note**
- +------------------------------------------------------------------------+
- | Operation | Result | $DEVICE | $ZA | $TEST | X | $ZEOF |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X:n | Normal | 0 | 0 | 1 | Data | 0 |
- | | Termination | | | | Read | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X:n | Timeout with | 0 | 0 | 0 | empty | 0 |
- | | no data read | | | | string | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | | Timeout with | | | | Partial | |
- | READ X:n | partial data | 0 | 0 | 0 | data | 0 |
- | | read | | | | | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | | | 1,Device | | | empty | |
- | READ X:n | End of File | detected | 9 | 1 | string | 1 |
- | | | EOF | | | | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X:0 | Normal | 0 | 0 | 1 | Data | 0 |
- | | Termination | | | | Read | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X:0 | No data | 0 | 0 | 0 | empty | 0 |
- | | available | | | | string | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | | Timeout with | | | | Partial | |
- | READ X:0 | partial data | 0 | 0 | 0 | data | 0 |
- | | read | | | | | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | | | 1,Device | | | empty | |
- | READ X:0 | End of File | detected | 9 | 1 | string | 1 |
- | | | EOF | | | | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X | Error | 1,<error | 9 | n/c | empty | 0 |
- | | | signature> | | | string | |
- +------------------------------------------------------------------------+
+ A socket can move from one device to another using DETACH/ATTACH. A socket
+ does not carry I[O]CHSET with it while being moved. Such a socket uses the
+ I[O]CHSET of the device it is ATTACHed to. If there is input still
+ buffered, this may cause unintentional consequences in the application if
+ I[O]CHSET changes. GT.M does not detect (or report) a change in I[O]CHSET
+ due to DETACH/ATTACH.
- With WRITE:
+ Example:
- * The FIFO device does non-blocking writes. If a process tries to WRITE
- to a full FIFO and the WRITE would block, the device implicitly tries
- to complete the operation up to a default of 10 times. If the
- gtm_non_blocked_write_retries environment variable is defined, this
- overrides the default number of retries. If the retries do not succeed
- (remain blocked), the WRITE sets $DEVICE to "1,Resource temporarily
- unavailable", $ZA to 9, and produces an error. If the GT.M process has
- defined an EXCEPTION, $ETRAP or $ZTRAP, the error trap may choose to
- retry the WRITE after some action or delay that might remove data from
- the FIFO device.
- * While it is hung, the process will not respond to <CTRL-C>.
+ GTM>set tcp="seerv" open tcp:(listen="6321:TCP":attach="serv")::"SOCKET"
- With CLOSE:
+ GTM>zshow "D"
+ /dev/pts/9 OPEN TERMINAL NOPAST NOESCA NOREADS TYPE WIDTH=80 LENG=24
+ seerv OPEN SOCKET TOTAL=1 CURRENT=0
+ SOCKET[0]=serv DESC=3 LISTENING PASSIVE NOTRAP PORT=6321
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
- * The FIFO is not deleted unless the DELETE qualifier is specified.
- * If a process closes the FIFO with the DELETE qualifier, the FIFO
- becomes unavailable to new users at that time.
- * All processes currently USEing the FIFO may continue to use it, until
- the last process attached to it CLOSES it, and is destroyed.
- * Any process OPENing a FIFO with the same name as a deleted FIFO
- creates a new one to which subsequent OPENs attach.
+ GTM>set tcp="seerv" o tcp:(listen="6322:TCP":attach="serv2")::"SOCKET"
- A process must have read and write privileges on a FIFO to access it. File
- permissions have no affect on a process that already has the FIFO open.
+ GTM>zshow "D"
+ /dev/pts/9 OPEN TERMINAL NOPAST NOESCA NOREADS TYPE WIDTH=80 LENG=24
+ seerv OPEN SOCKET TOTAL=2 CURRENT=1
+ SOCKET[0]=serv DESC=3 LISTENING PASSIVE NOTRAP PORT=6321
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
+ SOCKET[1]=serv2 DESC=4 LISTENING PASSIVE NOTRAP PORT=6322
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
-3 FIFO_Deviceparameter_Summary
- FIFO Deviceparameter Summary
+ At this point, the socket device "seerv" has two sockets associated with
+ it.
- The following table summarizes the deviceparameters that can be used with
- FIFOs.
+ The following command moves the "serv" socket to the "socketpool" device.
- +------------------------------------------------------------------------+
- | File Format Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | CMD | DESCRIPTION |
- |--------------------+-----+---------------------------------------------|
- | [NO]FIXED | O | Controls whether records have fixed length. |
- |--------------------+-----+---------------------------------------------|
- | [Z]LENGTH=intexpr | U | Controls the virtual page length. |
- |--------------------+-----+---------------------------------------------|
- | RECORDSIZE=intexpr | O | Specifies the maximum record size. |
- |--------------------+-----+---------------------------------------------|
- | VARIABLE | O | Controls whether records have variable |
- | | | length. |
- |--------------------+-----+---------------------------------------------|
- | [Z]WIDTH=intexpr | U | Sets the device's logical record size and |
- | | | enables WRAP. |
- |--------------------+-----+---------------------------------------------|
- | [Z][NO]WRAP | O/U | Controls the handling of records longer |
- | | | than the device width. |
- +------------------------------------------------------------------------+
+ GTM>use tcp:detach="serv"
- +------------------------------------------------------------------------+
- | File Access Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | CMD | COMMENT |
- |-----------------+-----+------------------------------------------------|
- | | | Specifies that the FIFO should be deleted when |
- | | | the last user closes it. If specified on an |
- | | | OPEN, DELETE is activated only at the time of |
- | DELETE | C | the close. No new attachements are allowed to |
- | | | a deleted FIFO and any new attempt to use a |
- | | | FIFO with the name of the deleted device |
- | | | creates a new device. |
- |-----------------+-----+------------------------------------------------|
- | GROUP=expr | O/C | Specifies file permissions for other users in |
- | | | owner's group. |
- |-----------------+-----+------------------------------------------------|
- | OWNER=expr | O/C | Specifies file permissions for owner of file. |
- |-----------------+-----+------------------------------------------------|
- | | | Specifies that CLOSE replace the name of a |
- | RENAME=expr | C | disk file with the name specified by the |
- | | | expression. |
- |-----------------+-----+------------------------------------------------|
- | SYSTEM=expr | O/C | Specifies file permissions for owner of file |
- | | | (same as OWNER). |
- |-----------------+-----+------------------------------------------------|
- | UIC=expr | O/C | Specifies the file's owner ID. |
- |-----------------+-----+------------------------------------------------|
- | WORLD=expr | O/C | Specifies file permissions for users not in |
- | | | the owner's group. |
- +------------------------------------------------------------------------+
+ GTM>use 0 zshow "D"
+ /dev/pts/9 OPEN TERMINAL NOPAST NOESCA NOREADS TYPE WIDTH=80 LENG=24
+ seerv OPEN SOCKET TOTAL=1 CURRENT=0
+ SOCKET[0]=serv2 DESC=4 LISTENING PASSIVE NOTRAP PORT=6322
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
+ socketpool OPEN SOCKET TOTAL=1 CURRENT=0
+ SOCKET[0]=serv DESC=3 LISTENING PASSIVE NOTRAP PORT=6321
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
-2 Using_Null_Devices
- Using Null Devices
+ Notice how socket "serv" is now associated with the pseudo socket device
+ "socketpool". Its only purpose is to hold detached sockets.
- Null devices comprise of a collection of system purpose devices that
- include /dev/null, /dev/zero, /dev/random, and /dev/urandom.
+ GTM>set tcp2="s2" o tcp2:::"SOCKET"
- o /dev/null returns a null string on READ and sets $ZEOF
- o /dev/random and /dev/urandom return a random value on READ and set
- $ZEOF
- o /dev/zero returns 0's on READ and does not set $ZEOF
+ This creates a new socket device.
- A null device discards all output. GT.M maintains a virtual cursor
- position for null devices as it does for terminals on output. Use null
- devices for program testing and debugging, or for jobs that permit I/O to
- be discarded under certain circumstances. For example, JOB processes must
- have input and output devices associated with them, even though they do
- not use them. Null devices are low overhead never-fail alternatives for
- certain classes of I/O.
+ GTM>zshow "D"
+ /dev/pts/9 OPEN TERMINAL NOPAST NOESCA NOREADS TYPE WIDTH=80 LENG=24
+ s2 OPEN SOCKET TOTAL=0 CURRENT=0
+ seerv OPEN SOCKET TOTAL=1 CURRENT=0
+ SOCKET[0]=serv2 DESC=4 LISTENING PASSIVE NOTRAP PORT=6322
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
+ socketpool OPEN SOCKET TOTAL=1 CURRENT=0
+ SOCKET[0]=serv DESC=3 LISTENING PASSIVE NOTRAP PORT=6321
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
-3 Null_Deviceparameter_Summary
- Null Deviceparameter Summary
+ The following command moves the serv socket from the socketpool to the
+ tcp2 device.
- +------------------------------------------------------------------------+
- | Null Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |------------------------------------------------------------------------|
- | O: Applies to the OPEN command |
- | |
- | U: Applies to the USE command |
- | |
- | C: Applies to the CLOSE command |
- |------------------------------------------------------------------------|
- | | | Controls device-specified error |
- | | | handling. For the null device this is |
- | EXCEPTION=expr | O/U/C | only EOF handling and therefore |
- | | | exceptions can never be invoked except |
- | | | by a READ. |
- |-------------------+---------+------------------------------------------|
- | [NO]FILTER[=expr] | U | Controls some $X,$Y maintenance. |
- |-------------------+---------+------------------------------------------|
- | [Z]LENGTH=intexpr | U | Controls the length of the virtual page. |
- |-------------------+---------+------------------------------------------|
- | [Z]WIDTH=intexpr | U | Controls maximum size of a record. |
- |-------------------+---------+------------------------------------------|
- | [Z][NO]WRAP | O/U | Controls handling of records longer than |
- | | | the maximum width. |
- |-------------------+---------+------------------------------------------|
- | X=intexpr | U | Sets $X to intexpr. |
- |-------------------+---------+------------------------------------------|
- | Y=intexpr | U | Sets $Y to intexpr. |
- +------------------------------------------------------------------------+
+ GTM>use tcp2:attach="serv"
+ GTM>use 0 zshow "D"
+ /dev/pts/9 OPEN TERMINAL NOPAST NOESCA NOREADS TYPE WIDTH=80 LENG=24
+ s2 OPEN SOCKET TOTAL=1 CURRENT=0
+ SOCKET[0]=serv DESC=3 LISTENING PASSIVE NOTRAP PORT=6321
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
+ seerv OPEN SOCKET TOTAL=1 CURRENT=0
+ SOCKET[0]=serv2 DESC=4 LISTENING PASSIVE NOTRAP PORT=6322
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
+ socketpool OPEN SOCKET TOTAL=0 CURRENT=-1
-3 Null_Device_Examples
- Null Device Examples
+5 DOWNSCROLL
+ DOWNSCROLL
- This section contains examples of null device usage.
+ DOWNSCROLL Applies to: TRM
- Example:
+ DOWNSCROLL Applies to: Terminals and Printers
- GTM>do ^runrep
- runrep;
- zprint ^runrep
- set dev="/dev/null"
- set hdr="********* REPORT HEADER ************"
- open dev use dev
- set x="" write hdr,!,$zdate($horolog),?30,$job,!
- for set x=$order(^tmp($job,x)) quit:x="" do REPORT
- quit
- REPORT;
- ;large amount of code
- quit;
+ If $Y=0, DOWNSCROLL does nothing. Otherwise, DOWNSCROLL moves the cursor
+ up one line on the terminal screen and decrements $Y by one. DOWNSCROLL
+ does not change the column position or $X. Some terminal hardware may not
+ support DOWNSCROLL.
- This program produces a report derived from the information in the global
- variable ^tmp. The unspecified routine REPORT may potentially contain a
- large amount of code. To see that the basic program functions without
- error, the programmer may discard the output involved in favor of watching
- the function. To run the program normally, the programmer simply has to
- change the variable dev to name another device and the routine REPORT
- writes to the dev device.
+5 ECHO
+ ECHO
+
+ [NO]ECHO Applies to: TRM
+
+ [NO]ECHO Applies to: Terminals and Printers
+
+ Enables or disables the echo of terminal input. If you disable ECHO, the
+ EDITING functions will be disabled and any input is not available for
+ later recall.
+
+ By default, terminal input ECHOes.
Example:
- job ^X:(in="/dev/null":out="/dev/null":err="error.log")
- JOB ^X:(IN="/dev/null":OUT="/dev/null":ERR="error.log")
+ use $principal:noecho
- This example issues a GT.M JOB command to execute the routine ^X in
- another process. This routine processes a large number of global variables
- and produces no output. In the example, the JOBbed process takes its input
- from a null device, and sends its output to a null device. If the JOBbed
- process encounters an error, it directs the error message to error.log.
+ This example disables the echo of terminal input.
-2 Using_PIPE_Devices
- Using PIPE Devices
+5 EDITING
+ EDITING
- A PIPE device is used to access and manipulate the input and/or output of
- a shell command as a GT.M I/O device. GT.M maintains I/O status variables
- for a PIPE device just as it does for other devices. An OPEN of the device
- starts a sub-process. Data written to the device by the M program is
- available to the process on its STDIN. The M program can read the STDOUT
- and STDERR of the sub-process. This facilitates output only applications,
- such as printing directly from a GT.M program to an lp command; input only
- applications, such as reading the output of a command such as ps; and
- co-processing applications, such as using iconv to convert data from one
- encoding to another.
+ [NO]EDITING Applies to: TRM
- A PIPE is akin to a FIFO device. Both FIFO and PIPE map GT.M devices to
- UNIX pipes, the conceptual difference being that whereas a FIFO device
- specifies a named pipe, but does not specify the process on the other end
- of the pipe, a PIPE device specifies a process to communicate with, but
- the pipes are unnamed. Specifically, an OPEN of a PIPE creates a
- subprocess with which the GT.M process communicates.
+ Enables the EDITING mode for the $PRINCIPAL device. If you enable EDITING,
+ GT.M allows the use of the left and right cursor movement keys and certain
+ <CTRL> characters within the current input line. You can recall the last
+ input line using the up or down arrow key. The editing functions are the
+ same as during direct mode command input as described in the "Line
+ Editing" section of the "Operating & Debugging in Direct Mode" chapter
+ except that backspace is not treated the same as the erase character from
+ terminfo which is usually delete (ASCII 127). NOECHO disables EDITING
+ mode.
- A PIPE device is specified with a "PIPE" value for mnemonicspace on an
- OPEN command.
+ Set the environment variable gtm_principal_editing to specify the mode for
+ EDITING. For example, gtm_principal_editing="EDITING" enables EDITING mode
+ at GT.M startup. You can also specify the mode for INSERT. For example,
+ gtm_principal_editing="NOINSERT:EDITING". If you specify both modes then
+ separate them with a colon (":") and put them in any order.
+
+ By default, EDITING mode is disabled.
+
+ If you enable the EDITING mode, escape sequences do not terminate READs.
+
+ Enabling PASTHRU mode supersedes EDITING mode.
+
+ If any of the EDITING <CTRL> characters are in the CTRAP list, their
+ editing functions are not available since CTRAP takes precedence. However
+ the EDITING <CTRL> characters takes precedence over the TERMINATOR list.
**Note**
- GT.M ignores the mnemonicspace specification on an OPEN of a previously
- OPEN device and leaves the existing device with its original
- characteristics.
+ M READ EDITING depends on the values of $X and $Y being correct. If the
+ application sends its own escape sequences or control characters, which
+ change the cursor position, it must properly update $X and $Y before doing
+ a M READ with EDITING enabled to ensure correct formatting during input.
-3 PIPE_Characteristics
- PIPE Characteristics
+5 EMPTERM
+ EMPTERM
- The following characteristics of PIPE may be helpful in using them
- effectively.
+ [NO]EMPT[ERM] Applies to: TRM
- With Read:
+ Allows an "Erase" character on an empty input line to terminate a READ or
+ READ # command. The default is NOEMPTERM. The gtm_principal_editing
+ environment variable specifies the initial setting of [NO]EMPTERM. The
+ TERMINFO specified by the current value of the TERM environment variable
+ defines capnames values "kbs" and/or "kdch1" with character sequences for
+ "Erase." If "kbs" or "kdch1" are multi-character values, you must also
+ specify the ESCAPE or EDIT deviceparameters for EMPTERM recognition.
- A READ with no timeout reads whatever data is available to be read; if
- there is no data to be read, the process hangs until some data becomes
- available.
+ The erase character as set and shown by stty also terminates a READ
+ command with an empty input line. You can set this erase character to
+ various values using the stty shell command. Typical values of an erase
+ character are <CTRL-H> and <CTRL-?>. Characters set and shown with stty
+ setting must match what the terminal emulator sends.
- A READ with a timeout reads whatever data is available to be read, and
- returns; if there is no data to be read, the process waits for a maximum
- of the timeout period, an integer number of seconds, for data to become
- available (if the timeout is zero, it returns immediately, whether or not
- any data was read). If the READ returns before the timeout expires, it
- sets $TEST to TRUE(1); if the timeout expires, it sets $TEST to FALSE (0).
- When the READ command does not specify a timeout, it does not change
- $TEST. READ specifying a maximum length (for example, READ X#10 for ten
- characters) reads until either the PIPE has supplied the specified number
- of characters, or a terminating delimiter.
+ The environment variable TERM must specify a terminfo entry that matches
+ both what the terminal (or terminal emulator) sends and expects.
- The following table shows the result and values of I/O status variables
- for various READ operations on a PIPE device.
+5 ERASELINE
+ ERASELINE
- +------------------------------------------------------------------------+
- | Operation | Result | $DEVICE | $ZA | $TEST | X | $ZEOF |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X:n | Normal | 0 | 0 | 1 | Data | 0 |
- | | Termination | | | | Read | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X:n | Timeout with | 0 | 0 | 0 | empty | 0 |
- | | no data read | | | | string | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | | Timeout with | | | | Partial | |
- | READ X:n | partial data | 0 | 0 | 0 | data | 0 |
- | | read | | | | | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | | | 1,Device | | | empty | |
- | READ X:n | End of File | detected | 9 | 1 | string | 1 |
- | | | EOF | | | | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X:0 | Normal | 0 | 0 | 1 | Data | 0 |
- | | Termination | | | | Read | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X:0 | No data | 0 | 0 | 0 | empty | 0 |
- | | available | | | | string | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | | Timeout with | | | | Partial | |
- | READ X:0 | partial data | 0 | 0 | 0 | data | 0 |
- | | read | | | | | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | | | 1,Device | | | empty | |
- | READ X:0 | End of File | detected | 9 | 1 | string | 1 |
- | | | EOF | | | | |
- |-----------+---------------+------------+-----+-------+---------+-------|
- | READ X | Error | 1,<error | 9 | n/c | empty | 0 |
- | | | signature> | | | string | |
- +------------------------------------------------------------------------+
+ ERASELINE Applies to: TRM
+
+ ERASELINE Applies to: Terminals and Printers
+
+ Clears the current line from the physical cursor position to the end of
+ the line. ERASELINE does not affect the physical cursor position, or $X
+ and $Y.
+
+5 ESCAPE
+ ESCAPE
+
+ [NO]ESCAPE Applies to: TRM
+
+ [NO]ESCAPE Applies to: Terminals and Printers
+
+ Enables or disables GT.M processing of escape sequences.
+
+ The following events result when a terminal has ESCAPE sequence processing
+ enabled. When an <ESC> or <CSI> arrives in the terminal input, the device
+ driver verifies the sequence that follows as a valid ANSI escape sequence,
+ terminates the READ, and sets $ZB to contain the entire escape sequence.
+ In the case of a READ * when ESCAPE sequence processing is enabled and an
+ escape introducer is read, the entire escape sequence is returned in $ZB
+ and the ASCII representation of the first character is returned in the
+ argument of the READ *.
+
+ When escape processing is disabled, READ *x returns 27 in x for an <ESC>.
+ If the escape introducer is also a TERMINATOR, $ZB has a string of length
+ one (1), and a value of the $ASCII() representation of the escape
+ introducer; otherwise, $ZB holds the empty string. For single character
+ and short fixed reads with NOESCAPE, the remaining characters in the
+ escape sequence will be in the input stream for subsequent READS
+ regardless of [NO]TYPEAHEAD.
+
+ An application that operates with (NOESCAPE:TERM=$C(13)) must provide
+ successive READ * commands to remove the remaining characters in the
+ escape sequence from the input stream.
+
+ By default, ESCAPE processing is disabled.
+
+ Example:
+
+ use $principal:(noescape:term=$c(13))
+
+ This example disables the escape sequence processing and set $c(13) as the
+ line terminator.
+
+5 EXCEPTION
+ EXCEPTION
+
+ EXCEPTION=expr Applies to: All devices
+
+ EXCEPTION=expr Applies to: All devices
+
+ Defines an error handler for an I/O device. The expression must contain a
+ fragment of GT.M code (for example, GOTO ERRFILE) that GT.M XECUTEs when
+ the driver for the device detects an error, or an entryref to which GT.M
+ transfers control, as appropriate for the current gtm_ztrap_form.
+
+5 FILTER
+ FILTER
- With WRITE:
+ [NO]FILTER[=expr] Applies to: TRM SOC NULL
- The PIPE device does non-blocking writes. If a process tries to WRITE to a
- full PIPE and the WRITE would block, the device implicitly tries to
- complete the operation up to a default of 10 times. If the
- gtm_non_blocked_write_retries environment variable is defined, this
- overrides the default number of retries. If the retries do not succeed
- (remain blocked), the WRITE sets $DEVICE to "1,Resource temporarily
- unavailable", $ZA to 9, and produces an error. If the GT.M process has
- defined an EXCEPTION, $ETRAP or $ZTRAP, the error trap may choose to retry
- the WRITE after some action or delay that might remove data from the PIPE
- device.
+ [NO]FILTER[=expr] Applies to: Terminals and Printers, Socket Device, and
+ NULL Device
- With WRITE /EOF:
+ Specifies character filtering for specified cursor movement sequences.
+ Filtering requires character by character examination of all output and
+ reduces I/O performance.
- WRITE /EOF to a PIPE device flushes, sets $X to zero (0) and terminates
- output to the created process, but does not CLOSE the PIPE device. After a
- WRITE /EOF, any additional WRITE to the device discards the content, but
- READs continue to work as before. A WRITE /EOF signals the receiving
- process to expect no further input, which may cause it to flush any output
- it has buffered and terminate. You should explicitly CLOSE the PIPE device
- after finishing all READs. If you do not want WRITE /EOF to flush any
- pending output including padding in FIXED mode or a terminating EOL in
- NOFIXED mode, SET $X=0 prior to the WRITE /EOF.
+ Each FILTER deviceparameter can have only one argument. However, multiple
+ FILTER deviceparameters can appear in a single USE command, each with
+ different arguments.
- To avoid an indefinite hang doing a READ from a created process that
- buffers its output to the input of the PIPE device, READ with timeout
- (typically 0).
+ By default, GT.M does not perform output filtering. For GT.M to maintain
+ $X for non-graphic characters as described by the standard,
+ FILTER="CHARACTERS" must be enabled. Output filtering adds additional
+ overhead to I/O processing.
- With CLOSE:
+ Example:
- The CLOSE of a PIPE device prevents all subsequent access to the pipes
- associated with the device. Unless the OPEN that created the device
- specified INDEPENDENT, the process terminates. Note that any subsequent
- attempt by the created process to read from its stdin (which would be a
- closed pipe) returns an EOF and typical UNIX behavior would be to
- terminate on such an event.
+ use tcpdev:filter="NOESCAPE"
-3 PIPE_Device_Examples
- PIPE Device Examples
+ This example removes the effect of escape sequences on the maintenance $X
+ and $Y.
- The following examples show the use of deviceparameters and status
- variables with PIPE devices.
+5 FOLLOW
+ FOLLOW
- Example:
+ [NO]FOLLOW Applies to: SD
- pipe1;
- set p1="test1"
- open p1:(shell="/bin/sh":comm="cat")::"PIPE"
- for i=1:1:10 do
- . use p1
- . write i,":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ",!
- . read x
- . use $P
- . write x,!
- close p1
- quit
+ Configures READ to return only when it has a complete record or reaches
+ any specified timeout; it waits for more input rather than terminating on
+ an EOF (end-of-file) condition.
- This WRITEs 10 lines of output to the cat command and reads the cat output
- back into the local variable x. The GT.M process WRITEs each line READ
- from the PIPE to the principal device. This example works because "cat" is
- not a buffering command. The example above would not work for a command
- such as tr that buffers its input.
+ The USE command can switch a device from NOFOLLOW to FOLLOW or from FOLLOW
+ to NOFOLLOW. This provides a READ mode of operation similar to a tail -f
+ in UNIX.
- Example :
+5 HOSTSYNC
+ HOSTSYNC
- pipe3;
- set p1="test1"
- open p1:(shell="/bin/sh":command="tr -d e")::"PIPE"
- for i=1:1:1000 do
- . use p1
- . write i,":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ",!
- . read x:0
- . if '+$device use $principal write x,!
- use p1
- write /EOF
- for read x quit:$zeof use $principal write x,! use p1
- close p1
- quit
+ [NO]HOSTSYNC Applies to: TRM
- This shows the use of tr (a buffering command) in the created process for
- the PIPE device. To see the buffering effect the GT.M process WRITEs 1000
- lines to the PIPE device. Different operating systems may have different
- buffer sizes. Notice the use of the r x:0 and the check on $DEVICE in the
- loop. If $DEVICE is 0, WRITE x writes the data read to the principal
- device. No actual READs complete, however, until tr reaches its buffer
- size and writes to its stdout. The final few lines remain buffered by tr
- after the process finishes the first loop. The GT.M process then issues a
- WRITE /EOF to the PIPE causing tr to flush its buffered lines. In the
- final for loop the GT.M process uses the simple form of READ x from the
- PIPE followed by a WRITE of each line to the principal device until $zeof
- becomes TRUE.
+ [NO]HOSTSYNC Applies to: Terminals and Printers
- Example :
+ Enables or disables the use of XON/XOFF by the host to throttle input and
+ prevent impending buffer overruns for a terminal. This deviceparameter
+ provides a control mechanism for the host over asynchronous communication
+ lines to help prevent data loss when hardware is slow and/or processing
+ load is high.
- pipe4;
- set a="test"
- open a:(command="nestin":independent)::"PIPE"
- use a
- set key=$KEY
- write "Show ntestin still running after CLOSE of a",!
- write "The parent process of 1 shows the parent shell has exited after CLOSE of a"
- read line1,line2
- use $principal
- write !,line1,!,line2,!,!
- set k="ps -ef | grep -v grep | grep -v sh | grep -w '"_key_"' | awk '{print $2}'"
- set b="getpid"
- open b:(command=k:readonly)::"PIPE"
- use b
- read pid
- close a
- close b
- set k2="ps -ef | grep -v grep | grep -v sh | grep -w '"_pid_"'"
- set c="psout"
- open c:(command=k2:writeonly)::"PIPE"
- close c
- quit
+ By default, HOSTSYNC is disabled.
- This demonstrates that the created process nestin keeps running as an
- INDEPENDENT process after the GT.M process CLOSEs the pipe. This GT.M
- process uses another PIPE device to return the process id of ntestin and
- READ it into pid so that it may be killed by this or another process,
- should that be appropriate.
+5 KEY
+ KEY
+
+ Applies to: SD, PIPE, and FIFO
+
+ Specifies information about the key file to use for reading and writing
+ encrypted data. The syntax of the KEY deviceparameter is as follows:
+
+ KEY="key_name [IV]"
+
+ key_name is case-sensitive and must match a key name in the "files"
+ section of the gtmcrypt_config file. The optional IV specifies an
+ initialization vector to use for encryption and decryption.
+
+ For more information and an example, refer to the description of KEY
+ deviceparameter of OPEN.
+
+5 IKEY
+ IKEY
+
+ Applies to: SD, PIPE, and FIFO
+
+ IKEY allows the use of a seperate key to READ from a device; for example,
+ when a GT.M process is an element of a UNIX pipe. The format of the IKEY
+ deviceparameter is:
+
+ IKEY="key_name [IV]"
+
+ key_name is case-sensitive and must match a key name in the "files"
+ section of the gtmcrypt_config file. The optional IV specifies an
+ initialization vector to use for encryption and decryption.
+
+ For more information, refer to the description of KEY deviceparameter of
+ OPEN.
+
+5 INREWIND
+ INREWIND
+
+ Applies to: SD
+
+ Performs a REWIND on input when $PRINCIPAL identifies a device that
+ supports REWIND. Use this deviceparameter with $PRINCIPAL when redirected
+ from a file.
+
+5 INSEEK=strexpr
+ INSEEK=strexpr
+
+ Applies to: SD
+
+ Performs a SEEK on input when $PRINCIPAL identifies a device that supports
+ SEEK. Use this deviceparameter with $PRINCIPAL when redirected from a
+ file.
+
+5 IOERROR
+ IOERROR
+
+ IOERROR=expr Applies to: SOC
+
+ IOERROR=expr Applies to: Socket Device
+
+ Enables exception handling in socket devices. expr specifies the I/O error
+ trapping mode. A value equal to "TRAP" specifies that I/O errors on a
+ device raise error conditions. A value equal to "NOTRAP", or when IOERROR
+ is not specified, indicates that an I/O error on a device does not raise
+ error conditions.
**Note**
- "nestin.c" is a program which reads from standard input and writes to
- standard output until it see and EOF. It then loops for 300 1sec sleeps
- doing nothing. The purpose of using independent is as a server process
- which continues until it receives some other signal for termination.
+ GT.M currently handles exception handling at device level instead of
+ socket level.
Example:
- GTM>kill ^a
+ use sock:(ioerror="TRAP":exception="zgoto "_$zlevel_":error")
- GTM>zprint ^indepserver
- indepserver;
- read x
- write "received = ",x,!
- set ^quit=0
- for do quit:^quit
- . if $data(^a) write "^a = ",^a,!
- . Hang 5
+ This example enables exception handling in socket device sock and
+ specifies that all I/O errors on sock raise the error condition.
- GTM>set a="test"
+5 LENGTH
+ LENGTH
- GTM>open a:(command="mumps -run ^indepserver>indout":independent)::"pipe"
+ [Z]LENGTH=intexpr Applies to: TRM SOC SD FIFO PIPE NULL
- GTM>use a
+ [Z]LENGTH=intexpr Applies to: Terminals and Printers, Socket Device, and
+ NULL Device.
- GTM>write "instructions",!
+ Sets the virtual page length for an I/O device to the integer expression.
+ You can specify the virtual page length up to 1,048,576. The page length
+ controls the point at which the device driver automatically resets $Y to
+ 0.
- GTM>close a
+ By default, for terminals, GT.M uses the terminfo variable lines (which
+ may be from the terminal definition or from a stty command) as the initial
+ value for LENGTH. The default length for null device and socket device is
+ 66.
- GTM>zsystem "cat indout"
- received = instructions
+ Setting LENGTH to zero prevents resetting $Y to zero.
- GTM>set ^a=1
+ Example:
- GTM>zsystem "cat indout"
- received = instructions
- ^a = 1
- ^a = 1
- ^a = 1
+ use sock:(zwidth=80:znoff:zlength=24)
- GTM>s ^quit=1
+ This example sets the virtual page length to 24 for socket device sock.
- GTM>zsystem "cat indout"
- received = instructions
- ^a = 1
- ^a = 1
- ^a = 1
- ^a = 1
- GTM>
+5 LISTEN
+ LISTEN
- This is a simple example using a mumps process as a server.
+ LISTEN=expr Applies to: SOC
+
+ A new socket is allocated to listen for a connection. It is made the
+ current socket for the device, if the operation is successful.
+
+ expr specifies the protocol and the protocol-specific information.
+ Currently, GT.M supports TCP/IP and LOCAL (also known as UNIX domain)
+ socket protocols.
Example:
- pipe5;
- set p1="test1"
- set a=0
- open p1:(shell="/bin/sh":command="cat":exception="goto cont1")::"PIPE"
- set c=":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz"
- for i=1:1:10000 do
- . use p1
- . write i_c,!
- . use $principal write i,!
- use p1
- write /EOF
- for read x quit:$zeof use $principal write x,! use p1
- close p1
- quit
- cont1
- if $zeof quit
- if a=0 set a=i/2
- set z=$za
- ; use $device to make sure ztrap is caused by blocked write to pipe
- set d=$device
- if "1,Resource temporarily unavailable"=d DO
- . use $p
- . write "pipe full, i= ",i," $ZA = ",z,!
- . set i=i-1
- . use p1
- . for j=1:1:a read x use $principal write j,"-",x,! use p1
- quit
+ GTM>set tcp="seerv" open tcp:(listen="6321:TCP":attach="serv")::"SOCKET"
- This demonstrates WRITEs to a PIPE device with blocking. The WRITE loop
- has no READ to force the input pipe to fill up which blocks the cat
- output, causing cat to stop reading its input, letting the pipe acting as
- input on the PIPE device to fill up and creating the blocked condition.
- When the process takes the $ZTRAP to cont1 it tests $DEVICE to determine
- if the trap is caused by the full pipe. If so, it uses the for loop to
- read half the number of lines output by the main loop. It decrements i and
- returns to the original WRITE loop to retry the failed line and continue
- with the WRITEs to the pipe. Depending upon the configuration of the
- environment, it may trap several times before processing all lines.
+ GTM>use tcp:listen="6322:TCP"
-3 PIPE_Deviceparameter_Summary
- PIPE Deviceparameter Summary
+ GTM>use 0 zshow "D"
+ /dev/pts/9 OPEN TERMINAL NOPAST NOESCA NOREADS TYPE WIDTH=80 LENG=24
+ seerv OPEN SOCKET TOTAL=2 CURRENT=1
+ SOCKET[0]=serv DESC=3 LISTENING PASSIVE NOTRAP PORT=6321
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
+ SOCKET[1]=h12185825450 DESC=4 LISTENING PASSIVE NOTRAP PORT=6322
+ ZDELAY ZBFSIZE=1024 ZIBFSIZE=87380 NODELIMITER
- The following table summarizes the PIPE format deviceparameters.
+5 OKEY
+ OKEY
- +------------------------------------------------------------------------+
- | DEVICE PARAMETER | CMD | DESCRIPTION |
- |--------------------+-----+---------------------------------------------|
- | [NO]FIXED | O | Controls whether records have fixed length |
- |--------------------+-----+---------------------------------------------|
- | RECORDSIZE=intexpr | O | Specifies the maximum record size. |
- |--------------------+-----+---------------------------------------------|
- | VARIABLE | O | Controls whether records have variable |
- | | | length. |
- |--------------------+-----+---------------------------------------------|
- | [Z]WIDTH=intexpr | U | Sets the device's logical record size and |
- | | | enables WRAP. |
- |--------------------+-----+---------------------------------------------|
- | [Z][NO]WRAP | O/U | Controls the handling of records longer |
- | | | than the device width. |
- +------------------------------------------------------------------------+
+ Applies to: SD, PIPE, and FIFO
- The following table summarizes PIPE access deviceparamters.
+ OKEY allows the use of a seperate key for WRITE to a device; for example,
+ when a GT.M process is an element of a UNIX pipe. The format of the IKEY
+ deviceparameter is:
- +------------------------------------------------------------------------+
- | | | Specifies the command string to execut in a |
- | | | created process for the PIPE device. GT.M uses |
- | COMMAND=string | o | the default searching mechanism of the UNIX shell |
- | | | for creating the process and initiating its |
- | | | command(s). |
- |----------------+---+---------------------------------------------------|
- | SHELL=string | o | Specifies the path to a shell to be used instead |
- | | | of the default shell |
- |----------------+---+---------------------------------------------------|
- | | | Specifies a device handle for a return pipe to |
- | | | which the created process writes any standard |
- | STDERR=string | o | error output. The GT.M process can USE, READ, and |
- | | | CLOSE it, but cannot WRITE to it. When the GT.M |
- | | | process CLOSEs the PIPE device the PIPE device |
- | | | CLOSEs STDERR, if still OPEN. |
- |----------------+---+---------------------------------------------------|
- | WRITEONLY | o | Specifies that the GT.M process may only WRITE to |
- | | | the created process via the PIPE device. |
- |----------------+---+---------------------------------------------------|
- | | | Specifies that the GT.M process may only READ |
- | | | from the created process via the PIPE device. |
- | READONLY | o | Output from both the standard output and the |
- | | | standard error output of the created process is |
- | | | available unless STDERR is specified. |
- |----------------+---+---------------------------------------------------|
- | PARSE | o | Specifies that GT.M parse the COMMAND and issue |
- | | | an OPEN exception for any invalid command. |
- |----------------+---+---------------------------------------------------|
- | INDEPENDENT | o | Specifies that the created process continues to |
- | | | execute after the PIPE device is CLOSEd. |
- +------------------------------------------------------------------------+
+ OKEY="key_name [IV]"
-2 Using_Socket_Devices
- Using Socket Devices
+ key_name is case-sensitive and must match a key name in the "files"
+ section of the gtmcrypt_config file. The optional IV specifies an
+ initialization vector to use for encryption and decryption.
- SOCKET devices are used to access and manipulate sockets. A SOCKET device
- can have unlimited associated sockets. The default limit is 64. Set the
- environment variable gtm_max_sockets to the number of maximum associated
- sockets sockets that you wish to set for a GT.M process.
- $VIEW("MAX_SOCKETS") returns the current value of the maximum number of
- associated sockets.
+ For more information, refer to the description of KEY deviceparameter of
+ OPEN.
- At any time, only one socket from the collection can be the current
- socket. If there is no current socket, an attempt to READ from, or WRITE
- to the device, generates an error.
+5 OUTREWIND
+ OUTREWIND
- Sockets can be attached and detached from the collection of sockets
- associated with a device. Detached sockets belong to a pseudo-device
- called the "socketpool". A process can detach a socket from a device and
- later attach it to the same device or another device.
+ Applies to: SD
- **Caution**
+ Performs a REWIND on output when $PRINCIPAL identifies a device that
+ supports REWIND. Use this deviceparameter with $PRINCIPAL when redirected
+ to a file.
- Currently, GT.M does not produce an error if a socket is attached to a
- device having a different CHSET.
+5 OUTSEEK=strexpr
+ OUTSEEK=strexpr
- **Note**
+ Applies to: SD
- The GT.M socket device interface does not have the ability to pass sockets
- between related or unrelated processes. Currently error trapping operates
- on a device, rather than on a socket.
+ Performs a SEEK on output when $PRINCIPAL identifies a device that
+ supports SEEK. Use this deviceparameter with $PRINCIPAL when redirected to
+ a file.
-3 Message_Management
- Message Management
+5 PASTHRU
+ PASTHRU
- From an application perspective, the transport layers used by a socket
- device are stream-oriented, with no provisions for implicit application
- messages. Therefore, the following are two common protocols used to
- segment application messages.
+ [NO]PASTHRU Applies to: TRM
- 1. One method is to use a, typically small, fixed length message
- containing the length of the next, variable length, message. In GT.M a
- simplistic writer might be:
+ [NO]PASTHRU Applies to: Terminals and Printers
- Write $Justify($Length(x),4),x
+ Enables or disables interpretation of the ERASE character for a terminal.
+ PASTHRU shifts management of handling and response to ERASE characters in
+ the input stream from GT.M to the application code.
- A corresponding simplistic reader might be:
+ Exercise caution with PASTHRU in debugging, because using a PASTHRU
+ terminal in Direct Mode is somewhat awkward.
- read len#4,x#len
+ [NO]TTSYNC must be used with [NO]PASTHRU to control XON/XOFF handling.
- The advantage of this approach is that the message content (the value
- of x in the code fragments above) can contain any character. The
- disadvantage is that detecting that the protocol has become
- desynchronized is a problem.
+ By default, the device driver operates NOPASTHRU.
- 2. The other common method is to place a delimiter between each
- application message. The protocol breaks if a message ever includes a
- delimiter as part of its content.
+ PASTHRU supersedes line editing.
- The SOCKET device provides a facility for recognizing delimiters because
- parsing messages for delimiters is cumbersome.
+5 READSYNC
+ READSYNC
-3 Socket_Read_Operation
- Socket Read Operation
+ [NO]READSYNC Applies to: TRM
- TCP/IP is a stream-based protocol that guarantees that bytes arrive in the
- order in which they were sent. However, it does not guarantee that they
- will be grouped in the same packets.
+ Enables or disables automatic output of <XON> before a READ and <XOFF>
+ after a READ.
- If packets arrive infrequently, or at varying rates that are sometimes
- slow, a short interval can waste CPU cycles checking for an unlikely
- event. On the other hand, if the handling of packets is time critical, a
- long interval can introduce an undesirable latency. If packets arrive in a
- rapid and constant flow (an unusual situation), the interval doesn't
- matter as much, as there is always something in the buffer for the READ to
- work with. If you do not specify MOREREADTIME, SOCKET READ implements a
- dynamic approach of using a longer first interval of 200 ms when it finds
- no data, then shortening the interval to 10 ms when data starts to arrive.
- If you specify an interval, the SOCKET device always uses the specified
- interval and does not adjust dynamically.
+ By default, the terminal drivers operate NOREADSYNC.
- Most SOCKET READ operations terminate as a result of the first condition
- detected from (a) receipt of delimiters, (b) receipt of the maximum number
- of characters, or (c) expiration of a timeout. Note that all of these
- conditions are optional, and a specific READ may specify zero or more of
- them. This section refers to these three conditions as "defined
- terminating conditions". If a SOCKET READ is not subject to any of the
- defined terminating conditions, it terminates after it has received at
- least one character followed by an interval with no new characters. An
- error can also terminate a READ. While none of the terminating conditions
- is satisfied, the READ continues.
+5 REWIND
+ REWIND
- The following flowchart represents the logic of a SOCKET READ.
+ REWIND Applies to: SD
-3 Socket_Read_Termination_Conditions
- Socket Read Termination Conditions
+ REWIND places the file pointer to the beginning of the file.
- A SOCKET READ operation terminates if any of the following conditions are
- met:
+ By default, USE does not REWIND.
- +------------------------------------------------------------------------+
- | Terminating | Argument Contains | $Device | $Key | $Test |
- | Conditions | | | | |
- |----------------+-------------------------+---------+-----------+-------|
- | Error | Empty String | Error | Empty | 1 |
- | | | String | String | |
- |----------------+-------------------------+---------+-----------+-------|
- | Timeout* | Data received before | Empty | Empty | 0 |
- | | timeout | String | String | |
- |----------------+-------------------------+---------+-----------+-------|
- | Delimiter* | Data up to, but not | Empty | Delimiter | 1 |
- | | including the delimiter | String | String | |
- |----------------+-------------------------+---------+-----------+-------|
- | Fixed Length | String of Fixed Length | Empty | Empty | 1 |
- | Met* | | String | String | |
- |----------------+-------------------------+---------+-----------+-------|
- | Width | Full width String | Empty | Empty | 1 |
- | | | String | String | |
- |----------------+-------------------------+---------+-----------+-------|
- | | One (1) to as many | | | |
- | | characters as provided | | | |
- | | by the transport | | | |
- | | interface before | | | |
- | | waiting for an interval | | | |
- | | (in milliseconds) | | | |
- | | specified by | | | |
- | | MOREREADTIME with no | | | |
- | | additional input. If | | | |
- | | MOREREADTIME is not | | | |
- | | specified, buffer is | | | |
- | Buffer Emptied | checked every 200 | Empty | Empty | 1 |
- | | milliseconds for its | String | String | |
- | | first input and then | | | |
- | | every 10 milliseconds | | | |
- | | until no new input | | | |
- | | arrives and no other | | | |
- | | terminating conditions | | | |
- | | are met. | | | |
- | | | | | |
- | | IF MOREREADTIME is | | | |
- | | specified, READ uses | | | |
- | | that value exclusively | | | |
- | | for buffer checks. | | | |
- +------------------------------------------------------------------------+
+ REWIND on redirected output for $PRINCIPAL is the same as OUTREWIND.
- * denotes Defined Terminating Conditions
+5 SEEK=strexpr
+ SEEK=strexpr
- A non-fixed-length read, with no timeout and no delimiters (the sixth row
- in the above table) requires a complex implementation of sequence of READs
- to ensure a predictable result. This is because the transport layer stream
- fragments delivered to the reader has only accidental correspondence with
- the operations performed by the writer. For example, the following:
+ SEEK Applies to: SD
- Write "Message 1","Message 2" is presented to the reader as the stream
- "Message1Message2" but it can take from one (1) to 18 READ commands to
- retrieve the entire stream.
+ Positions the current file pointer to the location specified in strexpr.
+ The format of strexpr is a string of the form "[+|-]integer" where an
+ unsigned value specifies an offset from the beginning of the file, and an
+ explicitly signed value specifies an offset relative to the current file
+ position. For STREAM or VARIABLE format, the positive intexpr after any
+ sign is a byte offset, while for a FIXED format, it is a record offset. In
+ order to deal with the possible presence of a Byte Order Marker (BOM),
+ SEEK for a FIXED format file written in a UTF character set must follow at
+ least one prior READ since the device was created.
- Messaging protocol should implement READ in any of the following ways:
+ SEEK on redirected input for $PRINCIPAL is the same as INSEEK.
- 1. Use a delimiter to separate messages (generic READ and possibly a
- larger value for MOREREADTIME).
- 2. Specify messages as <length, value> pairs (a pair of fixed-length
- READs (READ # ) and possibly a larger value for MOREREADTIME).
- 3. Parse the bytes or characters as they come in (possibly a smaller
- value for MOREADTIME)
+5 SOCKET
+ SOCKET
-3 Read_Command
- Read Command
+ SOCKET=expr Applies to: SOC
- The READ command may be used to obtain data from a socket. A READ
- operation terminates if any of the following are detected, in the order
- specified below:
+ Makes the socket specified by the handle named in expr the current socket
+ for the Socket device . If the named socket is a listening socket, it
+ checks for an incoming connection request and if one is available, it
+ accepts the request and creates a new connected socket in which case $KEY
+ provides information on the new socket Specifying a socket handle not
+ contained in the Socket device generates an error.
- +------------------------------------------------------------------------+
- | Terminating | Argument Contains | $Device | $Key |
- | Condition | | | (Continued) |
- |------------------+----------------------------+---------+--------------|
- | Error | Empty string | Error | Empty string |
- | | | string | |
- |------------------+----------------------------+---------+--------------|
- | Timeout | Data received before | Empty | Empty string |
- | | timeout | string | |
- |------------------+----------------------------+---------+--------------|
- | Delimiter | Data up to, but not | Empty | Delimiter |
- | | including the delimiter | string | string |
- |------------------+----------------------------+---------+--------------|
- | Fixed length met | String of fixed length | Empty | Empty string |
- | | | string | |
- |------------------+----------------------------+---------+--------------|
- | | One (1) to as many | | |
- | Buffer emptied | characters as happen to be | Empty | Empty string |
- | | provided by the transport | string | |
- | | interface | | |
- +------------------------------------------------------------------------+
+ **Note**
- A non-fixed-length read, with no timeout and no delimiters requires a
- complex implementation of sequence of READs to ensure a predictable
- result. This is because the transport layer stream fragments delivered to
- the reader has only accidental correspondence with the operations
- performed by the writer. For example, the following
+ SOCKET is compatible with DELIMITER only.
- Write "Message 1","Message 2"
+5 TERMINATOR
+ TERMINATOR
- is presented to the reader as the stream "Message1Message2" but it can
- take from one (1) to 18 READ commands to retrieve the entire stream.
+ [NO]TERMINATOR[=expr] Applies to: TRM
-3 WRITE_Command
- WRITE Command
+ Specifies which of the 256 ASCII characters terminate a READ. For example,
+ TERMINATOR=$C(0) makes <NUL> the terminator.
- The WRITE command sends data to a socket.
+ When NOESCAPE is in effect, TERMINATOR controls whether or not <ESC> or
+ <CSI> are treated as terminators, however, when ESCAPE processing is
+ enabled, the entire escape sequence is treated as a terminator regardless
+ of the TERMINATOR specification.
- The WRITE command for SOCKET devices accepts following controlmnemonics on
- a bound socket:
+ When EDITING is enabled, the control characters used for editing are not
+ treated as terminators even if they are in the TERMINATOR list.
- /L[ISTEN][(numexpr)]
+ You can define any control character as a terminator, but they are all
+ single character.
- Where numexpr is in the range 1-5 and specifies the listen queue depth.
+ When the terminal is in UTF-8 mode (chset=utf8,) GT.M limits the
+ terminator characters to the first 127 which are common between ASCII and
+ Unicode. In M mode, any of the 256 characters may be specified a
+ terminator.
- /W[AIT][(timeout)]
+ In UTF-8 mode, if CR is in the terminator list (either by default or
+ explicitly,) GT.M ignore the following LF to keep with the standard
+ Unicode line terminator scheme.
- Where timeout is a "numexpr" that specifies how long a server waits for a
- connect before returning control to the GT.M routine.
+ NOTERMINATOR eliminates all terminators. When a terminal has all
+ terminators disabled, fixed length READ and READ * terminate on receipt of
+ some number of characters, and a timed READ terminates on timeout, but any
+ other READ only terminates when the input fills the terminal read buffer.
- WRITE /WAIT can also be used to wait for data to be available for reading
- in addition to waiting for a connection.
+ By default, terminals recognize <CR>, <LF>, and <ESC> as terminators (that
+ is, TERMINATOR=$C(10, 13,27)). TERMINATOR="" restores the default. In
+ UTF-8 mode, the usual Unicode line terminators are also included in the
+ default set of terminators.
- "WRITE !" inserts the character(s) of the first I/O delimiter (if any) to
- the sending buffer. If "ZFF=expr" has been used to define a delimiter,
- "WRITE #" inserts the characters of that delimiter. Otherwise WRITE # has
- no effect on the stream content. WRITE ! and WRITE # always maintain $X
- and $Y in a fashion that emulates a terminal cursor position except when
- the device is OPENed with a UTF CHSET because terminals are in display
- columns while sockets are in codepoints.
+ Example:
-3 Socket_Device_Operation
- Socket Device Operation
+ GTM> USE $P:TERM=$C(26,13,11,7)
- Each socket may be in one of the following states:
+ This example enables the ASCII characters <SUB>, <CR>, <VT> and <BEL> as
+ READ terminators.
- * Created - indicates that the socket exists.
- * Bound - indicates that the socket exists and is bound to a port; a
- "Bound socket" needs a listen queue which is established by a WRITE
- /LISTEN [after a USE].
- * Connected - indicates that the socket exists and has a connection.
+5 TRUNCATE
+ TRUNCATE
- A server socket used for accepting new connections goes through the first
- two states in one step with a single OPEN or in two steps with an OPEN and
- a USE. When a server does a WRITE /WAIT on a Bound socket, a client can
- establish a connection which Creates another server socket that is
- Connected. In server operation, $KEY supplies the port value when a socket
- is bound (important when port 0 is specified to get the system to choose
- the port), and a socket handle when a Connected socket is created. A
- client socket goes through the first and third states with a single OPEN
- or in two steps with an OPEN and a USE.
+ [NO]TRUNCATE Applies to: SD
-3 Socket_Deviceparameter_Summary
- Socket Deviceparameter Summary
+ Enables or disables overwriting of existing data in sequential files.
+ Because the position of each record depends on the prior record, a WRITE
+ destroys the ability to reliably position to subsequent records in a file.
+ Therefore, by default (NOTRUNCATE), GT.M permits WRITEs only when the file
+ pointer is positioned at the end-of-file. When a device has TRUNCATE
+ enabled, a WRITE issued when the file pointer is not at end-of-file
+ truncates the file by destroying all data from the file pointer to the
+ end-of-file.
- +------------------------------------------------------------------------+
- | Error Processing Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-----------------+---------+--------------------------------------------|
- | EXCEPTION=expr | O/U/C | Controls device-specific error handling. |
- |-----------------+---------+--------------------------------------------|
- | | | If $LENGTH(expr) and ("Tt"[$EXTRACT(expr)) |
- | IOERROR=expr | O/U | then Error Trapping is enabled; otherwise |
- | | | the application must check $DEVICE for |
- | | | errors. |
- +------------------------------------------------------------------------+
+ By default, OPEN accesses files NOTRUNCATE, which does not allow
+ overwriting of sequential files.
- +------------------------------------------------------------------------+
- | Format Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |--------------------+---------+-----------------------------------------|
- | [NO]DELIMITER=expr | O/U | Specifies socket delimiter(s). |
- |--------------------+---------+-----------------------------------------|
- | [NO]FILTER=expr | U | Specifies character filtering for |
- | | | socket output. |
- |--------------------+---------+-----------------------------------------|
- | LENGTH=expr, or | | Sets virtual page length for socket |
- | | U | device. |
- | ZLENGTH=expr | | |
- |--------------------+---------+-----------------------------------------|
- | ICHSET=expr | O/U/C | Specifies input character set |
- |--------------------+---------+-----------------------------------------|
- | OCHSET=expr | O/U/C | Specifies output character set |
- |--------------------+---------+-----------------------------------------|
- | [Z][NO]WRAP | O/U | Controls handling of records longer |
- | | | than the device width. |
- |--------------------+---------+-----------------------------------------|
- | [Z]WIDTH=expr | U | Controls the maximum length of an |
- | | | output message. |
- |--------------------+---------+-----------------------------------------|
- | Z[NO]FF=expr | O/U | Controls whether and what characters to |
- | | | send in response to a WRITE #. |
- +------------------------------------------------------------------------+
+ This deviceparameter may not be supported by your platform.
- +------------------------------------------------------------------------+
- | Socket Establishment/Disconnect Deviceparameters |
- |------------------------------------------------------------------------|
- | DEVICEPARAMETER | COMMAND | COMMENT |
- |-----------------+---------+--------------------------------------------|
- | CONNECT=expr | O/U | expr specifies protocol, and protocol |
- | | | specific information |
- |-----------------+---------+--------------------------------------------|
- | ZLISTEN=expr | O/U | Similar to CONNECT but binds the socket |
- | | | for subsequent /LISTEN and /WAIT |
- +------------------------------------------------------------------------+
+5 TTSYNC
+ TTSYNC
-3 Socket_Device_Examples
- Socket Device Examples
+ [NO]TTSYNC Applies to: TRM
+
+ Enables or disables recognition of XON/XOFF for terminal output.
+
+ **Note**
+
+ A terminal may have its own handling of XON/XOFF, controlled by a set-up
+ mode or by switches. If an application requires program recognition of
+ <CTRL-S> and <CTRL-Q>, the terminals may require reconfiguration.
+
+5 TYPEAHEAD
+ TYPEAHEAD
+
+ [NO]TYPEAHEAD Applies to: TRM
+
+ [NO]TYPEAHEAD Applies to: Terminals and Printers
+
+ Enables or disables type-ahead buffering for a terminal. When TYPEAHEAD is
+ disabled, any pending input which has not yet been read will be discarded
+ before input is read for each READ argument. When TYPEAHEAD is enabled,
+ any input not read by one READ argument will remain available for the next
+ READ argument or command.
+
+ The size of the type-ahead buffer limits the amount of data entered at the
+ terminal that the device driver can store in anticipation of future READs.
+
+ By default, the terminal device driver accepts TYPEAHEAD.
+
+5 UPSCROLL
+ UPSCROLL
+
+ UPSCROLL Applies to: TRM
+
+ Moves the cursor down one line on the terminal screen. If $Y=LENGTH-1,
+ UPSCROLL sets $Y=0. Otherwise UPSCROLL increments $Y by one. If the cursor
+ is physically at the bottom of the page, the screen scrolls up one line.
+ UPSCROLL does not change the column position or $X.
+
+5 WIDTH
+ WIDTH
+
+ [Z]WIDTH=intexpr Applies to: TRM SOC NULL SD FIFO PIPE
+
+ [Z]WIDTH=intexpr Applies to: Terminals and Printers, Socket Device, NULL
+ Device, PIPE, and Sequential Files
+
+ Sets the device's logical record size and enables WRAP. The default WIDTH
+ for SD and FIFO is taken from the RECORDSIZE.
+
+ NOWRAP and WIDTH supersede each other. When WIDTH and NOWRAP appear
+ together on the same USE command, the final one controls the device
+ behavior. For a terminal, WIDTH=0 is equivalent to WIDTH=n:NOWRAP, where n
+ is the default length of a logical record on that terminal.
+
+ Terminals inherit their default WIDTH in GT.M from the invoking shell
+ environment. The default WIDTH for null and socket device is 255.
+
+ For SD and SOC which support 1MB strings, you can specify WIDTH up to
+ 1,048,576.
+
+ For non fixed format, always include the line terminator in WIDTH
+ otherwise you get NULL reads after records which are WIDTH wide.
+
+ In UTF-8 mode and TRM, SD, and FIFO output, the WIDTH deviceparameter is
+ in units of display-columns and is used with $X to control truncation and
+ WRAPing for output and maintenance of $X and $Y for input.
+
+ In UTF-8 mode and SOC, the WIDTH deviceparameter is in units of Unicode
+ code points and is used with $X to control truncation and wrapping for
+ output and maintenance of $X and $Y for input.
+
+ In M mode if WIDTH is set to 0, GT.M uses the default WIDTH of the TRM and
+ SOC devices. USE x:WIDTH=0 is equivalent to USE
+ x:(WIDTH=<device-default>:NOWRAP. For SD and FIFO devices in M mode, the
+ device default is the RECORDSIZE.
+
+ GT.M format control characters, FILTER, and the device WIDTH and WRAP also
+ have an effect on $X.
- This section contains examples on Socket Device usage.
-
- server;
- set portno=6321,delim=$c(13)
- set tcpdev="server$"_$j,timeout=30
- open tcpdev:(ZLISTEN=portno_":TCP":delim=$c(13):attach="server"):timeout:"SOCKET"
- use tcpdev
- write /listen(1)
- write /wait(timeout)
- write !,"Hello Client------I am Server",!
- read x:10
-
- ;client.m
- client;
- set host="localhost"
- set portno=6321
- set delim=$c(13)
- set tcpdev="client$"_$j,timeout=30
- open tcpdev:(connect=host_":"_portno_":TCP":delim=$c(13):attach="client"):timeout:"SOCKET"
- use tcpdev
- read x:10
- read y:10
- use $P
- write "y=",y,!
-
- This example transmits the message "Hello Client ---- I am Server" from
- the Server to the client.
+ In UTF-8 mode and SOC output, the WIDTH deviceparameter specifies the
+ number of characters in Unicode.
- You can start a GT.M process in response to a connection request made
- using inetd/xinetd. The following example uses inetd/xinetd to implement a
- listener which responds to connections and messages just as the prior
- example.
+5 WRAP
+ WRAP
- In the configuration file for xinetd, define a new service called
- gtmserver. Set socket_type to "stream" and wait should be "no" as in the
- following snippet:
+ [Z][NO]WRAP Applies to: TRM SOC NULL SD FIFO
- service gtmserver
- {
- disable = no
- type = UNLISTED
- port = 7777
- socket_type = stream
- wait = no
- user = gtmuser
- server = /path/to/startgtm
- }
+ [Z][NO]WRAP Applies to: Terminals and Printers, FIFO, Socket Device, NULL
+ Device, and Sequential Files
- If you define the server in /etc/services, the type and port options are
- not needed. For more information, the xinetd.conf man page for more
- details.
+ Enables or disables automatic record termination. When the current record
+ size ($X) reaches the maximum WIDTH and the device has WRAP enabled, GT.M
+ starts a new record, as if the routine had issued a WRITE ! command.
- If you are using inetd, a line should be added to /etc/inetd.conf with the
- sockettype "stream", protocol "tcp", and the "nowait" flag should be
- specified as in the example below, which assumes a gtmserver service is
- defined in /etc/services:
+ NOWRAP causes GT.M to require a WRITE ! to terminate the record. NOWRAP
+ allows $X to become greater than the device WIDTH for terminals.
- gtmserver stream tcp nowait gtmuser /path/to/startgtm
+ By default, WIDTH sets WRAP. When WIDTH and NOWRAP appear together on the
+ same USE command, the last one controls the device behavior.
- In both of the above examples, "gtmuser" is the name of the user the
- service gtmserver should be run as, and "/path/to/startgtm" is the name of
- a script which defines some environment variables needed by GT.M before
- starting it. Please check the man page for inetd.conf on your system since
- the details may be slightly different.
+ By default, records WRAP.
- The minimum variables are $gtm_dist which should specify the directory
- containing the GT.M distribution and $gtmroutines. As an example:
+ Example:
- #!/bin/bash
- cd /path/to/workarea
- export gtm_dist=/usr/local/gtm
- export gtmroutines="/var/myApp/o(/var/myApp/r) $gtm_dist"
- export gtmgbldir=/var/myApp/g/mumps.dat
- $gtm_dist/mumps -r start^server
+ See WRAP examples in the OPEN deviceparameters section.
- When start^server begins, the $PRINCIPAL device will already be connected
- and $KEY will contain "ESTABLISHED|socket_handle|remote_ip_address". In
- most cases, a USE should be executed to set various device parameters such
- as delimiters.
+5 X
+ X
- The ZSHOW "D" command provides both the local and remote addresses and
- ports:
+ X=intexpr Applies to: TRM
- 0 OPEN SOCKET TOTAL=1 CURRENT=0
- SOCKET[0]=h11135182870 DESC=0 CONNECTED ACTIVE NOTRAP
- REMOTE=10.1.2.3 at 53731 LOCAL=10.2.3.4 at 7777
- ZDELAY ZBFSIZE=1024 ZIBFSIZE=0
+ X=intexpr Applies to: Terminals and Printers
-2 I/O_Commands
- I/O Commands
+ $X positions the cursor to a vertical column on the terminal. If NOWRAP is
+ enabled or intexpr<WIDTH, GT.M sets $X=intexpr. If WRAP is enabled and
+ intexpr>WIDTH, GT.M sets $X=intexpr#WIDTH, where # is the GT.M modulo
+ operator. The resulting $X determines the actual physical position.
- This section describes the following GT.M I/O commands:
+ To ensure that $Y and $X match what is occurring visually on the terminal,
+ the GT.M deviceparameters and the device characteristics must match at all
+ times.
- * OPEN establishes a connection from a GT.M process to a device.
- * USE declares a device as the current source of input and destination
- for output.
- * READ accepts characters from the current device into a global or local
- variable.
- * WRITE sends characters to the current device.
- * CLOSE breaks the connection between a GT.M process and a device.
+ The terminal hardware may affect physical cursor positioning. The X
+ deviceparameter does not change the cursor row or update $Y.
-3 Open
- Open
+5 Y
+ Y
- The OPEN command establishes a connection from a GT.M process to a device.
+ Y=intexpr Applies to: TRM
- The format of the OPEN command is:
+ Y=intexpr Applies to: Terminals and Printers
- O[PEN][:tvexpr] expr[:[(keyword[=expr][:...])][:numexpr][:expr]][,...]
+ Positions the cursor to a horizontal row on the terminal.
- By default, when a device is unavailable, GT.M retries the OPEN
- indefinitely at approximately one second intervals. A device is
- unavailable when another process is using it exclusively, or when the
- OPENing process does not have the resources left to open the device.
+ GT.M sets $Y=intexpr#LENGTH, where # is the GT.M modulo operator. If
+ intexpr<LENGTH, the resulting $Y determines the physical position. If
+ intexpr>LENGTH, the cursor is positioned so that $Y=intexpr#LENGTH, where
+ # is the GT.M module operator. The terminal hardware may affect physical
+ cursor positioning.
- All other errors on OPEN raise an error condition and interrupt program
- flow. A timeout is a tool that lets a GT.M routine regain program control
- when a device remains unavailable. When the OPEN specifies a timeout, GT.M
- keeps retrying until either the OPEN succeeds or the timeout expires.
+ To ensure that $Y and $X match what is occurring visually on the terminal,
+ the GT.M deviceparameters and the device characteristics must match at all
+ times. For example, if a process initiates a subprocess that changes the
+ terminal wrap setting from NOWRAP, previously set with the GT.M USE
+ command to WRAP , GT.M does not reflect the change when the subprocess
+ completes. Therefore, wraps on the terminal do not reflect in the values
+ of $X and $Y.
- If OPEN establishes a connection with a device before the timeout expires,
- GT.M sets $TEST to TRUE (1). If the timeout expires, GT.M sets $TEST to
- FALSE (0). If an OPEN command does not specify a timeout, the execution of
- the command does not affect $TEST.
+ The Y deviceparameter does not change the cursor column or update $X.
- If a process has not previously OPENed a device, any deviceparameters not
- supplied on the OPEN take their default values. When reOPENing a device
- that it previously closed, a GT.M process restores all characteristics not
- specified on the OPEN to the values the device had when it was last
- CLOSEd, except with SD, FIFO, and PIPE. If you have a menu-driven
- application that OPENs and CLOSEs devices based on user selections, take
- care that every OPEN explicitly includes all deviceparameters important to
- the application.
+5 ZBFSIZE
+ ZBFSIZE
- GT.M treats sequential disk files differently and uses defaults for
- unspecified sequential disk file characteristics on every OPEN (i.e., GT.M
- does not retain sequential disk file characteristics on a CLOSE).
+ ZBFSIZE Applies to: SOC
- If a process OPENs an already OPEN device, GT.M modifies any
- characteristics that accept changes when a device is OPEN to reflect any
- new deviceparameter specifications.
+ ZBFSIZE Applies to: Socket Device
- In UTF-8 mode, the OPEN command recognizes ICHSET, OCHSET, and CHSET as
- three additional deviceparameters to determine the encoding of the the
- input / output devices.
+ Allocates a buffer used by GT.M when reading from a socket. The ZBFSIZE
+ deviceparameter should be at least as big as the largest message expected.
- In M mode, the OPEN command ignores ICHSET, OCHSET, CHSET, and PAD device
- parameters.
+ By default, the size of ZBFSIZE is 1024 and the maximum it can be is
+ 1048576.
- If an I/O device uses a multi-byte character encoding, every READ and
- WRITE operation of that device checks for well-formed characters according
- to the specified character encoding with ICHSET or OCHSET. If the I/O
- commands encounter an illegal sequence of bytes, they always trigger a
- run-time error; a VIEW "NOBADCHAR" does not prevent such errors. Strings
- created by $ZCHAR() and other Z equivalent functions may contain illegal
- sequences. The only way to input or output such illegal sequences is to
- specify character set "M" with one of these deviceparameters.
+5 ZDELAY
+ ZDELAY
-4 Examples_of_OPEN
- Examples of OPEN
+ Z[NO]DELAY Applies to: SOC
- Example:
+ Z[NO]DELAY Applies to: Socket Device
- set sd="report.dat" open sd:newversion
+ Controls buffering of data packets by the system TCP stack using the
+ TCP_NODELAY option to the SETSOCKOPT system call. This behavior is
+ sometimes known as the Nagle algorithm. The default is ZDELAY. This delays
+ sending additional packets until either an acknowledgement of previous
+ packets is received or an interval passes. If several packets are sent
+ from one end of a connection before the other end responds, setting
+ ZNODELAY may be desirable though at the cost of additional packets being
+ transmitted over the network. ZNODELAY must be fully spelled out.
- This OPENs a NEWVERSION of a sequential disk file named report.dat for
- both read and write access.
+5 ZFF
+ ZFF
-4 OPEN_Deviceparameters
- OPEN Deviceparameters
+ Z[NO]FF=expr Applies to: SOC
-4 OPEN_Deviceparameter_Table
- OPEN Deviceparameter Table
+ Z[NO]FF=expr Applies to: Socket Device
- +------------------------------------------------------------+
- | OPEN Deviceparameters |
- |------------------------------------------------------------|
- | OPEN DEVICEPARAMETER | TRM | SD | FIFO | PIPE | NULL | SOC |
- |------------------------------------------------------------|
- | TRM: Valid for terminals and printers |
- | |
- | SD: Valid for sequential disk files |
- | |
- | FIFO: Valid for FIFOs |
- | |
- | NULL: Valid for null devices |
- | |
- | PIPE: Valid for PIPEs |
- | |
- | SOC: Valid for Socket devices |
- |------------------------------------------------------------|
- | APPEND | | X | | | | |
- |----------------------+-----+----+------+------+------+-----|
- | ATTACH=expr | | | | | | X |
- |----------------------+-----+----+------+------+------+-----|
- | CHSET=encoding | X | X | X | X | X | X |
- |----------------------+-----+----+------+------+------+-----|
- | COMMAND=expr | | | | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | CONNECT=expr | | | | | | X |
- |----------------------+-----+----+------+------+------+-----|
- | [NO]DELIMITER | | | | | | X |
- |----------------------+-----+----+------+------+------+-----|
- | EXCEPTION=expr | X | X | X | | X | X |
- |----------------------+-----+----+------+------+------+-----|
- | FIFO | | | X | | | |
- |----------------------+-----+----+------+------+------+-----|
- | [NO]FIXED | | X | X | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | GROUP=expr | | X | X | | | |
- |----------------------+-----+----+------+------+------+-----|
- | ICHSET=encoding | X | X | X | X | X | X |
- |----------------------+-----+----+------+------+------+-----|
- | INDEPENDENT | | | | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | IOERROR=expr | | | | | | X |
- |----------------------+-----+----+------+------+------+-----|
- | [NO]NEWVERSION | | X | X | | | |
- |----------------------+-----+----+------+------+------+-----|
- | OCHSET=encoding | X | X | X | X | X | X |
- |----------------------+-----+----+------+------+------+-----|
- | OWNER=expr | | X | X | | | |
- |----------------------+-----+----+------+------+------+-----|
- | PARSE | | | | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | [NO]READONLY | | X | X | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | RECORDSIZE=intexpr | | X | X | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | REWIND | | X | | | | |
- |----------------------+-----+----+------+------+------+-----|
- | SHELL=expr | | | | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | STDERR=expr | | | | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | [NO]STREAM | | X | | | | |
- |----------------------+-----+----+------+------+------+-----|
- | SYSTEM=expr | | X | X | | | |
- |----------------------+-----+----+------+------+------+-----|
- | [NO]TRUNCATE | | X | X | | | |
- |----------------------+-----+----+------+------+------+-----|
- | UIC=expr | | X | X | | | |
- |----------------------+-----+----+------+------+------+-----|
- | VARIABLE | | X | X | X | | |
- |----------------------+-----+----+------+------+------+-----|
- | WORLD=expr | | X | X | | | |
- |----------------------+-----+----+------+------+------+-----|
- | [Z][NO]WRAP | X | X | X | X | X | X |
- |----------------------+-----+----+------+------+------+-----|
- | ZBFSIZE | | | | | | X |
- |----------------------+-----+----+------+------+------+-----|
- | Z[NO]DELAY | | | | | | X |
- |----------------------+-----+----+------+------+------+-----|
- | Z[NO]FF | | | | | | X |
- |----------------------+-----+----+------+------+------+-----|
- | ZIBFSIZE | | | | | | X |
- |----------------------+-----+----+------+------+------+-----|
- | ZLISTEN=expr | | | | | | X |
- +------------------------------------------------------------+
+ expr specifies a string of characters, typically in $CHAR() format to send
+ to socket device, whenever a routine issues a WRITE #. When no string is
+ specified or when ZFF="", then no characters are sent. The default in GT.M
+ is ZNOFF.
-3 Use
- Use
+ Example:
- The USE command selects the current device for READs (input) and WRITEs
- (output).
+ u tcpdev:(zwidth=80:zff=$char(13):zlength=24)
- The format of the USE command is:
+ This example sends $char(13) to the current socket of device tcpdev on
+ every WRITE #.
- U[SE][:tvexpr] expr[:(keyword[=expr][:...])][,...]
+5 ZIBFSIZE
+ ZIBFSIZE
- Example:
+ ZIBFSIZE Applies to: SOC
- USE $P:(X=0:Y=$Y-1:NOECHO)
+ ZIBFSIZE Applies to: Socket Device
- This example USEs the principal device. If that device is a terminal, the
- deviceparameters turn off echo and position the cursor to the beginning of
- the previous line.
+ Sets the buffer size used by the network software (setsockopt SO_RCVBUF).
+
+ The default and the maximum values depend on the platform and/or system
+ parameters.
4 Summary
Summary
@@ -14131,6 +16788,8 @@
|---------------------+-----+----+------+------+------+-----|
| [NO]ECHO | X | | | | | |
|---------------------+-----+----+------+------+------+-----|
+ | [NO]EMPT[ERM] | X | | | | | |
+ |---------------------+-----+----+------+------+------+-----|
| ERASELINE | X | | | | | |
|---------------------+-----+----+------+------+------+-----|
| ERASETAPE | | | | | | |
@@ -14143,12 +16802,28 @@
|---------------------+-----+----+------+------+------+-----|
| FLUSH | X | | | | | |
|---------------------+-----+----+------+------+------+-----|
+ | [NO]FOLLOW | | X | | | | |
+ |---------------------+-----+----+------+------+------+-----|
| [NO]HOSTSYNC | X | | | | | |
|---------------------+-----+----+------+------+------+-----|
+ | KEY | | X | X | X | | |
+ |---------------------+-----+----+------+------+------+-----|
+ | IKEY | | X | X | X | | |
+ |---------------------+-----+----+------+------+------+-----|
| IOERROR | | | | | | X |
|---------------------+-----+----+------+------+------+-----|
+ | INREWIND | | X | | | | |
+ |---------------------+-----+----+------+------+------+-----|
+ | INSEEK | | X | | | | |
+ |---------------------+-----+----+------+------+------+-----|
| [Z]LENGTH=expr | X | X | X | | X | X |
|---------------------+-----+----+------+------+------+-----|
+ | OKEY | | X | X | X | | |
+ |---------------------+-----+----+------+------+------+-----|
+ | OUTREWIND | | X | | | | |
+ |---------------------+-----+----+------+------+------+-----|
+ | OUTSEEK | | X | | | | |
+ |---------------------+-----+----+------+------+------+-----|
| [NO]PASTHRU | X | | | | | |
|---------------------+-----+----+------+------+------+-----|
| [NO]RCHK | | | | | | |
@@ -14157,6 +16832,8 @@
|---------------------+-----+----+------+------+------+-----|
| REWIND | | X | | | | |
|---------------------+-----+----+------+------+------+-----|
+ | SEEK=strexpr | | X | | | | |
+ |---------------------+-----+----+------+------+------+-----|
| SKIPFILE=intexpr | | | | | | |
|---------------------+-----+----+------+------+------+-----|
| SOCKET | | | | | | X |
@@ -14195,7 +16872,7 @@
|---------------------+-----+----+------+------+------+-----|
| ZIBUFSIZE | | | | | | X |
|---------------------+-----+----+------+------+------+-----|
- | ZLISTEN | | | | | | X |
+ | LISTEN | | | | | | X |
+-----------------------------------------------------------+
3 Close
@@ -14229,6 +16906,13 @@
This closes the device and, if it is a disk file, renames it to have the
type .SAV.
+ Example:
+
+ CLOSE SOCKDEV:(SOCKET="LOCALSOCK1":DELETE)
+
+ This deletes the socket file associated with LOCALSOCK1 if it is a
+ listening socket and closes only the named socket on the socket device.
+
4 CLOSE_Deviceparameters_Table
CLOSE Deviceparameters Table
@@ -14237,15 +16921,15 @@
|-----------------------------------------------|
| CLOSE DEVICEPARAMETER | TRM | SD | FIFO | SOC |
|-----------------------------------------------|
- | SD: Valid for sequential disk files |
+ | SD: Valid for sequential disk files |
| |
- | TRM: Valid for terminals and printers |
+ | TRM: Valid for terminals and printers |
| |
- | FIFO: Valid for FIFOs |
+ | FIFO: Valid for FIFOs |
| |
- | NULL: Valid for NULL devices |
+ | NULL: Valid for NULL devices |
| |
- | SOC: Valid for Socket devices |
+ | SOC: Valid for Socket devices |
|-----------------------------------------------|
| DELETE | | X | X | |
|-----------------------+-----+----+------+-----|
@@ -14327,6 +17011,10 @@
|--------------------+------+-----+-------|
| GROUP=expr | X | X | X |
|--------------------+------+-----+-------|
+ | KEY | X | X | |
+ |--------------------+------+-----+-------|
+ | IKEY | X | X | |
+ |--------------------+------+-----+-------|
| IOERROR=expr | X | X | |
|--------------------+------+-----+-------|
| [NO]HOSTSYNC | | X | |
@@ -14335,6 +17023,8 @@
|--------------------+------+-----+-------|
| NEWVERSION | X | | |
|--------------------+------+-----+-------|
+ | OKEY | X | X | |
+ |--------------------+------+-----+-------|
| OWNER=expr | X | X | X |
|--------------------+------+-----+-------|
| [NO]PASTHRU | | X | |
@@ -14363,6 +17053,8 @@
|--------------------+------+-----+-------|
| TERMINATOR=expr | | X | |
|--------------------+------+-----+-------|
+ | TIMEOUT=expr | | | X |
+ |--------------------+------+-----+-------|
| [NO]TRUNCATE | X | X | |
|--------------------+------+-----+-------|
| [NO]TTSYNC | | X | |
@@ -14395,7 +17087,7 @@
|--------------------+------+-----+-------|
| ZIBFSIZE | X | X | |
|--------------------+------+-----+-------|
- | ZLISTEN=expr | X | X | |
+ | LISTEN=expr | X | X | |
+-----------------------------------------+
1 Utility_Routines
@@ -14590,6 +17282,8 @@
WRITE $&sqrt(2)
;Call the routine get parms, with the parameter "INPUT" and the variable "inval", passed by reference.
DO &getparms("INPUT",.inval)
+ ;Call program increment in package "mathpak" without specifying a value for the first argument and the variable "outval" passed by reference as the second argument. All arguments which do not specify a value translate to default values in the increment program.
+ Do &mathpak.increment(,.outval)
The called routines follow the C calling conventions. They must be
compiled as position independent code and linked as a shareable library.
@@ -14660,19 +17354,14 @@
Example:
%/opt/SUNWspro/bin/cc -c -KPIC -I$gtm_dist increment.c decrement.c
- % ld -o libincrement.so -G increment.o decrement -lc
-
- **Note**
-
- The environment variable GTMXC_RPC has to be set (export GTMXC_RPC=1) to
- use the RPC mechanisms, which is not described in this manual.
+ % ld -o libcrement.so -G increment.o decrement -lc
On Linux x86:
Example:
% gcc -c -fPIC -I$gtm_dist increment.c decrement.c
- % gcc -o libincrement.so -shared increment.o decrement.o
+ % gcc -o libcrement.so -shared increment.o decrement.o
2 External_Calls
External Calls
@@ -14737,6 +17426,30 @@
gtm_pointertofunc_t : For passing callback function pointers.
+ **Note**
+
+ If an external call's function argument is defined in the external call
+ table, GT.M allows invoking that function without specifying a value of
+ the argument. All non-trailing and output-only arguments arguments which
+ do not specify a value translate to the following default values in C:
+
+ o All numeric types: 0
+ o gtm_char_t * and gtm_char_t **: Empty string
+ o gtm_string_t *: A structure with 'length' field matching the
+ preallocation size and 'address' field being a NULL pointer.
+
+ In the mathpak package example, the following invocation translate inval
+ to the default value, that is, 0.
+
+ GTM>do &mathpak.increment(,.outval)
+
+ If an external call's function argument is defined in the external call
+ table and that function is invoked without specifying the argument, ensure
+ that the external call function appropriately handles the missing
+ argument. As a good programming practice, always ensure that count of
+ arguments defined in the external call table matches the function
+ invocation.
+
gtmxc_types.h also includes definitions for the following entry points
exported from libgtmshr:
@@ -14943,13 +17656,17 @@
Specification of a pre-allocation value should follow these rules:
* Pre-allocation is an unsigned integer value specifying the number of
- bytes allocated on the system heap to the pointer passed into the
- external call.
- * Pre-allocating on a type with a direction input or input/output
+ bytes to be allocated on the system heap with a pointer passed into
+ the external call.
+ * Pre-allocating on a type with a direction of input or input/output
results in a GT.M error.
- * Pre-allocation is meaningful only on types char * and gtm_string_t *.
- On all other types the pre-allocation value specified will be ignored
- and the parameter will be allocated a default value for that type.
+ * Pre-allocation is meaningful only on types gtm_char_t * and
+ gtm_string_t *. On all other types the pre-allocation value specified
+ will be ignored and the parameter will be allocated a default value
+ for that type. With gtm_string_t * arguments make sure to set the
+ 'length' field appropriately before returning control to GT.M. On
+ return from the external call, GT.M uses the value in the length field
+ as the length of the returned value, in bytes.
* If the user does not specify any value, then the default
pre-allocation value would be assigned to the parameter.
* Specification of pre-allocation for "scalar" types (parameters which
@@ -14958,8 +17675,8 @@
**Important**
Pre-allocation is optional for all output-only parameters except
- gtm_string_t * and char *. Pre-allocation yields better management of
- memory for the external call.
+ gtm_string_t * and gtm_char_t *. Pre-allocation yields better management
+ of memory for the external call.
3 Callback_Mechanism
Callback Mechanism
@@ -15135,13 +17852,14 @@
Example : For preallocation:
- % echo $GTMXC
+ % echo $GTMXC_extcall
/usr/joe/extcall.xc
% cat extcall.xc
/usr/lib/extcall.sl
- prealloc: void gtm_pre_alloc(O:gtm_char_t *[12])
+ prealloc: void gtm_pre_alloc_a(O:gtm_char_t *[12])
% cat extcall.c
#include <stdio.h>
+ #include <string.h>
#include "gtmxc_types.h"
void gtm_pre_alloc_a (int count, char *arg_prealloca)
@@ -15671,7 +18389,7 @@
call-in invocations.
2. The external application should never call exit() unless it has called
gtm_exit() previously. GT.M internally installs an exit handler that
- should never be bypassed to have a clean shutdown of GT.M.
+ should never be bypassed.
3. The external application should never use any signals when GT.M is
active since GT.M reserves them for its internal use. GT.M provides
the ability to handle SIGUSR1 within M. An interface is provided by
@@ -15679,6 +18397,75 @@
gtm_malloc() and gtm_free() for memory management by C code that
executes in a GT.M process space for enhanced performance and improved
debugging.
+ 4. GT.M performs device input using the read() system service. UNIX
+ documentation recommends against mixing this type of input with
+ buffered input services in the fgets() family and ignoring this
+ recommendation is likely to cause loss of input that is difficult to
+ diagnose and understand.
+
+2 Type_Limits_for_Call-ins_and_Call-outs
+ Type Limits for Call-ins and Call-outs
+
+ Depending on the direction (I, O, or IO) of a particular type, both
+ call-ins and call-outs may transfer a value in two directions as follows:
+
+ Call-out: GT.M -> C -> GT.M Call-in: C -> GT.M -> C
+ | | | | | |
+ '-----'-----' '-----'-----'
+ 1 2 2 1
+
+ In the following table, the GT.M->C limit applies to 1 and the C->GT.M
+ limit applies to 2. In other words, GT.M->C applies to I direction for
+ call-outs and O direction for call-ins and C->GT.M applies to I direction
+ for call-ins and O direction for call-outs.
+
+ +------------------------------------------------------------------------+
+ | | GTM->C | C->GT.M |
+ |----------------+---------------------------+---------------------------|
+ | Type | Precision | Range | Precision | Range |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_int_t, | Full | [-2^31+1, | Full | [-2^31, |
+ | gtm_int_t * | | 2^31-1] | | 2^31-1] |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_uint_t, | Full | [0, 2^32-1] | Full | [0, 2^32-1] |
+ | gtm_uint_t * | | | | |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_long_t, | | [-2^63+1, | | [-2^63, |
+ | gtm_long_t * | 18 digits | 2^63-1] | 18 digits | 2^63-1] |
+ | (64-bit) | | | | |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_long_t, | | [-2^31+1, | | [-2^31, |
+ | gtm_long_t * | Full | 2^31-1] | Full | 2^31-1] |
+ | (32-bit) | | | | |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_ulong_t, | | | | |
+ | gtm_ulong_t * | 18 digits | [0, 2^64-1] | 18 digits | [0, 2^64-1] |
+ | (64-bit) | | | | |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_ulong_t, | | | | |
+ | gtm_ulong_t * | Full | [0, 2^32-1] | Full | [0, 2^32-1] |
+ | (32-bit) | | | | |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_float_t, | 6-9 | [1E-43, | 6 digits | [1E-43, |
+ | gtm_float_t * | digits | 3.4028235E38] | | 3.4028235E38] |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_double_t, | 15-17 | [1E-43, 1E47] | 15 digits | [1E-43, 1E47] |
+ | gtm_double_t * | digits | | | |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_char_t * | N/A | ["", 1MiB] | N/A | ["", 1MiB] |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_char_t ** | N/A | ["", 1MiB] | N/A | ["", 1MiB] |
+ |----------------+-----------+---------------+-----------+---------------|
+ | gtm_string_t * | N/A | ["", 1MiB] | N/A | ["", 1MiB] |
+ +------------------------------------------------------------------------+
+
+ **Note**s
+
+ o gtm_char_t ** is not supported for call-ins but they are included for
+ IO and O direction usage with call-outs.
+ o For call-out use of gtm_char_t * and gtm_string_t *, the specification
+ in the interface definition for preallocation sets the range for IO
+ and O, with a maximum of 1MiB.
1 Internationalization
Internationalization
@@ -16188,16 +18975,19 @@
3 %GBLDEF
%GBLDEF
- The %GBLDEF utility is available to assign a collation sequence to a
- global, check the collation sequence assigned to a global, or delete an
- existing collation sequence from a global. %GBLDEF will not modify the
- collation sequence for a global containing data.
+ Use the %GBLDEF utility to get, set, or kill the collation sequence of a
+ global variable mapped by the current global directory. %GBLDEF modifies
+ the collation sequence for neither a global containing data nor a global
+ whose subscripts span multiple regions. To change the collation sequence
+ for a global variable that contains data, extract the data, KILL the
+ variable, change the collation sequence, and reload the data. Use GDE to
+ modify the collation sequence of a global variable that spans regions.
4 Assigning
Assigning
- To assign a collation sequence to an individual global use the following
- extrinsic entry point:
+ To assign a collation sequence to an individual global use the extrinsic
+ entry point:
set^%GBLDEF(gname,nct,act)
@@ -16205,26 +18995,35 @@
* The first argument, gname, is the name of the global. If the global
name appears as a literal, it must be enclosed in quotation marks ("
- "). The leading caret symbol (^) must be included, and the name must
- be a legal M variable name.
- * The second argument, nct, is an integer that determines how numeric
- subscripts are to be handled. The value is FALSE (0) if numeric
- subscripts are to collate before strings, as in standard M, and TRUE
- (1) if numeric subscripts are to be handled like strings.
+ "). The must be a legal M variable name, including the leading caret
+ (^).
+ * The second argument, nct, is an integer that determines whether
+ numeric subscripts are treated as strings. The value is FALSE (0) if
+ numeric subscripts are to collate before strings, as in standard M,
+ and TRUE (1) if numeric subscripts are to be treated as strings (for
+ example, where 10 collates before 9).
* The third argument, act, is an integer specifying the active collation
- sequence - from 0, standard M collation, to 255.
+ sequence from 0, standard M collation, to 255.
**Note**
- set^%GBLDEF(gname) returns global specific characteristics, which do not
- reflect any [collation] characteristics defined for the database file at
- MUPIP CREATE time [from settings in the global directory]. Region
- collation may be seen by using the DSE DUMP -FILEHEADER command,
- implicitly in the case of M standard collation, as in that case no
- collation information is displayed.
+ set^%GBLDEF(gname) returns global specific characteristics, which can
+ differ from collation characteristics defined for the database file at
+ MUPIP CREATE time from settings in the global directory. Region collation
+ may be seen by using the DSE DUMP -FILEHEADER command, implicitly in the
+ case of M standard collation, as in that case no collation information is
+ displayed.
If the global contains data, this function returns a FALSE (0) and does
- not modify the global.
+ not modify the existing collation sequence definition.
+
+ If the global's subscripts span multiple regions, the function returns a
+ false (0). Use the global directory (GBLNAME object in GDE) to set
+ collation characteristics for a global whose subscripts span multiple
+ regions.
+
+ Always execute this function outside of a TSTART/TCOMMIT fence. If $TLEVEL
+ is non-zero, the function returns a false(0).
Example:
@@ -16237,7 +19036,7 @@
This deletes the global variable ^G, then uses the $$set%GBLDEF as an
extrinsic to set ^G to the collation sequence number 3 with numeric
subscripts collating before strings. Using $$set%GBLDEF as an argument to
- $SELECT results in a return message notifying whether or not the SET was
+ $SELECT provides a return value as to whether or not the set was
successful. $SELECT will return a "FAILED" message if the collation
sequence requested is undefined.
@@ -16247,22 +19046,25 @@
To examine the collation characteristics currently assigned to a global
use the extrinsic entry point:
- get^%GBLDEF(gname)
+ get^%GBLDEF(gname[,reg])
+
+ where gname specifies the global variable name. When gname spans multiple
+ regions, reg specifies a region in the span.
- which returns the data associated with the global name as a comma
- delimited string having these pieces:
+ This function returns the data associated with the global name as a comma
+ delimited string having the following pieces:
- * A truth-valued integer specifying FALSE (0) if numeric subscripts are
- to collate before strings, as in standard M, and TRUE (1) if numeric
- subscripts are to be handled like strings.
+ * A truth-valued integer specifying FALSE (0) if numeric subscripts
+ collate before strings, as in standard M, and TRUE (1) if numeric
+ subscripts are handled as strings.
* An integer specifying the collation sequence.
* An integer specifying the version, or revision level, of the currently
implemented collation sequence.
**Note**
- A "0" return from $$get^%gbldef(gname) indicates that the global has no
- special characteristics and uses the region default collation, while a
+ A "0" return from $$get^%gbldef(gname[,reg]) indicates that the global has
+ no special characteristics and uses the region default collation, while a
"0,0,0" return indicates that the global is explicitly defined to M
collation.
@@ -16274,20 +19076,22 @@
This example returns the collation sequence information currently assigned
to the global ^G.
- This function returns the value of the characteristics defined for the
- global, in contrast to $DATA(@gname), which returns information about data
- and descendants at the name level of the global.
-
4 Deleting
Deleting
To delete the collation characteristics currently assigned to a global,
- use the following extrinsic entry point:
+ use the extrinsic entry point:
kill^%GBLDEF(gname)
- If the global contains data, the function returns a false (0) and does not
- modify the global.
+ o If the global contains data, the function returns a false (0) and does
+ not modify the global.
+ o If the global's subscript span multiple regions, the function returns
+ a false (0). Use the global directory (GBLNAME object in GDE) to set
+ collation characteristics for a global whose subscripts span multiple
+ regions.
+ o Always execute this function outside of a TSTART/TCOMMIT fence. If
+ $TLEVEL is non-zero, the function returns a false (0).
2 Matching_Alternative_Patterns
Matching Alternative Patterns
@@ -16627,6 +19431,14 @@
should perform when an error occurs during routine execution. $ETRAP and
$ZTRAP can establish one or more error handling "actions".
+ **Note**
+
+ The environment variable gtm_etrap specifies an initial value of $ETRAP to
+ override the default value of "B" for $ZTRAP as the base level error
+ handler. The gtmprofile script sets gtm_etrap to "Write:(0=$STACK) ""Error
+ occurred: "",$ZStatus,!" which you can customize to suit your needs. For
+ more information, refer to "Processing Errors".
+
2 Program_Handling_of_Errors
Program Handling of Errors
@@ -16811,9 +19623,8 @@
QUIT:$QUIT "" QUIT
When a value is assigned to $ETRAP, the new value replaces the previous
- value. If the value of $ZTRAP is a non-empty one, $ZTRAP is implicitly
- NEWed, and the value of $ZTRAP becomes equal to the empty string; this
- ensures that at most one of $ETRAP and $ZTRAP is not the empty string.
+ value. The value of $ZTRAP becomes equal to the empty string without being
+ stacked.
3 Nesting_$ETRAP_and_using_$ESTACK
Nesting $ETRAP and using $ESTACK
@@ -16821,9 +19632,9 @@
When you need to set up a stratified scheme where one level of subroutines
use one error trap setting and another more nested subroutine uses a
different one; the more nested subroutine must NEW $ETRAP. When $ETRAP is
- NEWed, its old value is saved, and its current value is made equal to the
- empty string. A subsequent SET $ETRAP=<new-value> then establishes the
- error trapping code for the current execution level.
+ NEWed, its old value is saved and copied to the current value. A
+ subsequent SET $ETRAP=<new-value> then establishes the error trapping code
+ for the current execution level.
The QUIT command that reverts to the calling routine causes the NEWed
values to be unstacked, including the one for $ETRAP.
@@ -17091,64 +19902,6 @@
1 Triggers
Triggers
-2 Overview
- Overview
-
- GT.M allows you to set up a trigger mechanism that automatically executes
- a defined action in response to a database update operation on a matching
- global node.The trigger mechanism executes a fragment of M code (trigger
- code) "before" or "as part of" a database update. You can define the
- specifications of this mechanism in a Trigger Definition File. For a
- trigger on KILL (and ZKILL), GT.M executes trigger code "before" the KILL
- operation. For example, a trigger on KILL ^CIF(:,1) might clear old cross
- references. For a trigger on SET, GT.M executes trigger code "as part of"
- the SET operation. Within trigger logic, the ISV $ZTOLDVAL provides read
- access to the value of global node prior to the update and $ZTVALUE
- provides read/write access to the tentative SET value. This allows you to
- modify the tentative SET value before GT.M commits it to the database. The
- term "as part of" means that SET triggers execute intertwined with the SET
- operation. Although it is not yet committed the database, the tentative
- new value appears to the process as assigned but the process must SET
- $ZTVALUE to make any revision to the tentative value, because a SET of the
- global node would nest the trigger recursively - a pathological condition.
- GT.M executes SET triggers during a MERGE update where GT.M internally
- performs a series of SET operations and while performing a $INCREMENT()
- operation where GT.M internally performs a SET operation.For all triggers,
- GT.M handles the database update event and the triggered actions as an
- Atomic (all or nothing) transaction.
-
- Triggers meet many application needs including (but not limited to) the
- following:
-
- 1. Enforce schema-level consistency: Since database schema created in a
- normal M application are implicit, M applications implement logic to
- maintain and enforce conformance with an application schema. Using
- triggers to enforce schema-level consistency ensures all processes
- invoke the code uniformly, and increases code modularity and
- maintainability.
- 2. Allow an application to maintain one or more non-primary key indexes.
- For example, a trigger on updates to global nodes containing a
- customer id can maintain an index on the last name.
- 3. Implement business logic: For example, an update to an account could
- automatically trigger updates to related accounts.
- 4. Reducing replication traffic: Since the GT.M replication stream
- carries only the triggering updates, not the triggered updates,
- triggers reduce network traffic.
- 5. Automate application defined logging or journaling of updates or
- maintaining historical records. Triggers can be used to control these.
- 6. Implement referential integrity: For example, a trigger can prevent
- the posting of a bank transaction for an inactive account and display
- a rule violation message.
- 7. Debugging: Debugging an application with multiple concurrent accesses
- is hard. You can use triggers to establish "watch points" on global
- variable updates to trap incorrect accesses. For example, if an
- application is failing because certain global variable nodes either
- have incorrect values or when previously set values disappear. A
- trigger can be used to trap all such accesses.
- 8. Implement a dataflow based programming paradigm. Although not a
- primary goal of the implementation of triggers, you can use them to
- implement applications that use a dataflow programming paradigm.
-
2 Trigger_Definition
Trigger Definition
@@ -17232,7 +19985,7 @@
alphanumeric string of up to 21 characters starting with an alphabetic
character or a percent sign (%). The trailing part consists of an
automatically incremented number in the form of #n# where n is a whole
- number that monotonically increases from 1 to 9999999 that uniquely
+ number that monotonically increases from 1 to 999999 that uniquely
identifies a trigger for the same update. For example, if no trigger names
are specified in the trigger definition file, GT.M automatically generates
trigger names Account#1#, Account#2#, and Account#3# for the first three
diff --git a/sr_port/mupfndfil.c b/sr_port/mupfndfil.c
index f1d2fac..60d9b37 100644
--- a/sr_port/mupfndfil.c
+++ b/sr_port/mupfndfil.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -30,6 +30,8 @@
GBLREF jnl_gbls_t jgbl;
+error_def(ERR_NOUSERDB);
+
/* mupfndfil.c
* Description:
* For a region find if the corresponding database is present.
@@ -43,19 +45,20 @@ GBLREF jnl_gbls_t jgbl;
*/
boolean_t mupfndfil(gd_region *reg, mstr *filestr)
{
- uint4 ustatus;
char filename[MAX_FN_LEN];
mstr file, def, ret, *retptr;
+ uint4 ustatus;
switch(reg->dyn.addr->acc_meth)
{
case dba_mm:
case dba_bg:
break;
+# ifdef VMS
case dba_usr:
- util_out_print("REGION !AD maps to a non-GDS database. Specified function does not apply to a non-GDS database.",
- TRUE, REG_LEN_STR(reg));
- return FALSE;
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_NOUSERDB, 4, LEN_AND_LIT("specified function"), REG_LEN_STR(reg));
+ return FALSE; /* This is currently a VMS only possibility and has no corresponding test case */
+# endif
default:
util_out_print("REGION !AD has an unrecognized access method.", TRUE, REG_LEN_STR(reg));
return FALSE;
@@ -68,8 +71,7 @@ boolean_t mupfndfil(gd_region *reg, mstr *filestr)
{
def.addr = DEF_NODBEXT;
def.len = SIZEOF(DEF_NODBEXT) - 1;
- }
- else
+ } else
{
def.addr = DEF_DBEXT; /* UNIX need to pass "*.dat" but reg->dyn.addr->defext has "DAT" */
def.len = SIZEOF(DEF_DBEXT) - 1;
@@ -91,7 +93,7 @@ boolean_t mupfndfil(gd_region *reg, mstr *filestr)
{ /* Do not print error messages in case of call from mur_open_files().
* Currently we use "jgbl.mupip_journal" to identify a call from mupip_recover code */
util_out_print("REGION !AD's file !AD cannot be found.", TRUE, REG_LEN_STR(reg), LEN_AND_STR(file.addr));
- gtm_putmsg(VARLSTCNT(1) ustatus);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ustatus);
}
return FALSE;
}
diff --git a/sr_port/mupint.h b/sr_port/mupint.h
index 8f56bca..e1db768 100644
--- a/sr_port/mupint.h
+++ b/sr_port/mupint.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -20,6 +20,18 @@
#define NO_ONLINE_ERR_MSG "ONLINE qualifier for this region will be ignored"
+#define DEFAULT_ADJACENCY 10
+#define CHECK_ADJACENCY(BLK, LVL, CNTR) \
+{ \
+ GBLREF int muint_adj; \
+ GBLREF int4 mu_int_adj[]; \
+ GBLREF block_id mu_int_adj_prev[]; \
+ \
+ if (mu_int_adj_prev[LVL] <= BLK + muint_adj && mu_int_adj_prev[LVL] >= BLK - muint_adj) \
+ CNTR += 1; \
+ mu_int_adj_prev[LVL] = BLK; \
+}
+
typedef struct global_list_struct
{
block_id root;
diff --git a/sr_port/mupip.hlp b/sr_port/mupip.hlp
index 29749d4..ae174d9 100644
--- a/sr_port/mupip.hlp
+++ b/sr_port/mupip.hlp
@@ -45,6 +45,33 @@
A gtmgbldir value of mumps.gld tells MUPIP to look for a global directory
file mumps.gld in the current directory.
+ **Important**
+
+ FIS recommends against running GT.M components as root. When run as root,
+ GT.M components use the owner and group of the database file as the owner
+ and group of newly created journal files, backup files, snapshot files,
+ shared memory, and semaphores. In addition, they set the permissions on
+ the resulting files, shared memory, and semaphores, as if running as the
+ owner of the database file and as a member of the database file group.
+
+ **Note**
+
+ You can perform read operations on a GT.M database residing on a read-only
+ mounted filesystem. However, please note:
+
+ o The filesystem must remain read-only for the duration of any process
+ that opens a database file resident on it. If a read-only file system
+ is switched to read-write while GT.M processes have database files
+ open on it, and other processes update those databases, the read-only
+ processes are likely to read incorrect or corrupt data.
+ o When the filesystem is read-only the shared memory resources which are
+ typically shared among multiple processes instead become private to
+ each process, so memory resource use increases with each additional
+ concurrent process.
+ o M locks mapped to regions that map to database files on read-only
+ filesystems are visible only to the process that owns the locks, and
+ are invisible to other processes.
+
2 Operations
Operations
@@ -157,14 +184,15 @@
any element of the destination list is invalid, BACKUP rejects the
command with an error.
o region-list may specify more than one region of the current global
- directory in a list. Regions are separated by a comma, and wildcards
- can be used to specify them. Any region-name may include the wildcard
- characters * and % (remember to escape them to protect them from
- inappropriate expansion by the shell). Any region name expansion
- occurs in M (ASCII) collation order.
+ directory in a list. Regions are case insensitive, separated by a
+ comma, and wildcards can be used to specify them. Any region-name may
+ include the wildcard characters * and % (remember to escape them to
+ protect them from inappropriate expansion by the shell). Any region
+ name expansion occurs in M (ASCII) collation order.
o Depending on the type of backup, destination-list may be a single
directory, or a comma separated list of destinations including files,
- piped commands, or TCP sockets.
+ piped commands, or a TCP socket address (a combination of IPv4 or IPV6
+ hostname and a port number).
o Region-list and destination-list items are matched in order - the
first region is mapped to the first destination, the second to the
second destination, and so on. If GT.M encounters a region mapped to a
@@ -619,7 +647,7 @@
(234,881,024) blocks. This means, for example, that with an 8KB block
size, the maximum single database file size is 1,792GB (8KB*224M). Note
that this is the size of one database file -- a logical database (an M
- global variable name space) can consist of an arbitrary number of database
+ global variable namespace) can consist of an arbitrary number of database
files.
3 Region
@@ -807,7 +835,7 @@
Backups certain globals or to extract data from the database for use by
another system. The MUPIP EXTRACT command copies globals from the current
database to a sequential output file in one of three formats-GO, BINARY,
- or ZWR. The format of the EXTRACT command is:
+ or ZWR. The format of the MUPIP EXTRACT command is:
EXTR[ACT]
[
@@ -815,6 +843,7 @@
-FR[EEZE]
-LA[BEL]=text
-[NO]L[OG]
+ -R[EGION]=region-list
-S[ELECT]=global-name-list]
]
{-ST[DOUT]|file-name}
@@ -939,6 +968,21 @@
By default, EXTRACT operates -LOG.
+3 Region
+ Region
+
+ Restricts MUPIP EXTRACT to a set of regions. The format of the REGION
+ qualifier is:
+
+ -R[EGION]=region-list
+
+ region-list may specify more than one region of the current global
+ directory in a list. Regions are case-insensitive, separated by a comma,
+ and wildcards can be used to specify them. Any region-name may include the
+ wildcard characters * and % (remember to escape them to protect them from
+ inappropriate expansion by the shell). Any region name expansion occurs in
+ M (ASCII) collation order.
+
3 Select
Select
@@ -1045,7 +1089,13 @@
F[REEZE] {-OF[F] [-OV[ERRIDE]]|-ON [-R[ECORD]]} region-list
- o The region-list identifies the target of the FREEZE.
+ o The region-list identifies the target of the FREEZE. region-list may
+ specify more than one region of the current global directory in a
+ list. Regions are case-insensitive, separated by a comma, and
+ wildcards can be used to specify them. Any region-name may include the
+ wildcard characters * and % (remember to escape them to protect them
+ from inappropriate expansion by the shell). Any region name expansion
+ occurs in M (ASCII) collation order.
o MUPIP FREEZE waits for one minute so that concurrent KILL or MUPIP
REORG operations can complete. If the KILL or MUPIP REORG commands do
not complete within one minute, MUPIP FREEZE terminates operations and
@@ -1252,7 +1302,7 @@
cylinder. You can also choose two or three cylinders, with the assumption
that short seeks are fast.
- The format of the INTEG command is:
+ The format of the MUPIP INTEG command is:
I[NTEG]
[
@@ -1269,7 +1319,7 @@
-[NO]TR[ANSACTION][=integer]
-[NO]O[NLINE]
]
- {[-FILE] file-name|-REG[ION] region-name}
+ {[-FILE] file-name|-REG[ION] region-list}
o MUPIP INTEG requires specification of either file(s) or region(s).
o Press <CTRL-C> to stop MUPIP INTEG before the process completes.
@@ -1374,6 +1424,7 @@
prevent accelerated database damage.
o By default, INTEG checks all active index and data blocks in the
database.
+ o -FAST reports adjacency information.
o Incompatible with: -TN_RESET.
3 FIle
@@ -1508,13 +1559,13 @@
GT.M processes automatically cleans up these temporary snapshot files
under a wider variety of conditions.
o Temporary directory security settings must allow write access by the
- the MUPIP process and read access by all processes updating the
- database. MUPIP creates the temporary file with the same access as the
- database file so processes updating the database can write to the
- temporary file. If the database is encrypted, the updating processes
- write encrypted blocks to the snapshot file and the MUPIP INTEG
- process must start with access to appropriate key information as it
- does even -NOONLINE.
+ MUPIP process and read access by all processes updating the database.
+ MUPIP creates the temporary file with the same access as the database
+ file so processes updating the database can write to the temporary
+ file. If the database is encrypted, the updating processes write
+ encrypted blocks to the snapshot file and the MUPIP INTEG process must
+ start with access to appropriate key information as it does even
+ -NOONLINE.
o MUPIP INTEG -NOONLINE [-FAST] {-REGION|-FILE} clears the KILLs in
progress and Abandoned Kills flags if the run includes the entire
database and there are no incorrectly marked busy blocks.
@@ -1544,8 +1595,15 @@
Specifies that the INTEG parameter identifies one or more regions rather
than a database file. The format of the REGION qualifier is:
- -R[EGION]
+ -R[EGION]=region-list
+ o The region-list identifies the target of INTEG. region-list may
+ specify more than one region of the current global directory in a
+ list. Regions are case-insensitive, separated by a comma, and
+ wildcards can be used to specify them. Any region-name may include the
+ wildcard characters * and % (remember to escape them to protect them
+ from inappropriate expansion by the shell). Any region name expansion
+ occurs in M (ASCII) collation order.
o MUPIP INTEG -REGION does not require stand alone access to databases.
Instead, it freezes updates (but not reads) to the database during the
check. The region-list argument may specify more than one region of
@@ -1802,6 +1860,7 @@
-E[ND]=integer
-FI[LLFACTOR]=integer
-FO[RMAT]={GO|B[INARY]|Z[WR]]}
+ -[O]NERROR={STOP|PROCEED|INTERACTIVE}
-S[TDIN]
]
file-name
@@ -1934,6 +1993,20 @@
descending keys, or if the record set and record sizes are relatively
static in the face of updates, FILL_FACTOR won't provide much benefit.
+3 Onerror
+ Onerror
+
+ Determines the MUPIP LOAD behavior when it encounters an error. The format
+ of the ONERROR qualifier is:
+
+ -[O]NERROR={STOP|PROCEED|INTERACTIVE}
+
+ o STOP causes MUPIP LOAD to exit immediately.
+ o PROCEED proceeds to the next record.
+ o PROMPTS prompts to continue or stop.
+
+ By default MUPIP LOAD exits on encountering an error.
+
3 Stdin
Stdin
@@ -1996,7 +2069,7 @@
Competing activity generally increases the time required to perform a
REORG, as well as that of the competing operations.
- The format of the REORG command is:
+ The format of the MUPIP REORG command is:
REO[RG]
[
@@ -2005,13 +2078,9 @@
-FI[LL_FACTOR]=integer
-I[NDEX_FILL_FACTOR]=integer
-R[ESUME]
- -SAFEJNL
-S[ELECT]=global-name-list
- -STA[RTBLK]=hexa
- -STO[PBLK]=hexa
-T[RUNCATE][=percentage]
-UP[GRADE]
- -US[ER_DEFINED_REORG]=reorg_list
-REG[ION]=region-list
]
@@ -2043,6 +2112,16 @@
action or error is incomplete but does not adversely affect the
database structure, unless terminated with a kill -9.
+ **Caution**
+
+ REORG focuses on optimum adjacency and a change to even a single block can
+ cause it to perform a large number of updates with only marginal benefit.
+ Therefore, FIS recommends not running successive REORGs close together in
+ time as that can provide minimal benefit for a significant increase in
+ database and journal activity. For the same reason, FIS recommends careful
+ research and planning before using the -RESUME qualifier or complex uses
+ of -EXCLUDE and -SELECT.
+
Assume two scenarios of putting values of ^x(1) to ^x(10000). In the first
scenarios, fill values in a sequential manner. In the second scenario,
enter values for odd subscripts and then enter values for the even
@@ -2223,6 +2302,13 @@
-R[EGION]=region-list
+ region-list may specify more than one region of the current global
+ directory in a list. Regions are case-insensitive, separated by a comma,
+ and wildcards can be used to specify them. Any region-name may include the
+ wildcard characters * and % (remember to escape them to protect them from
+ inappropriate expansion by the shell). Any region name expansion occurs in
+ M (ASCII) collation order.
+
3 Select
Select
@@ -2393,7 +2479,7 @@
machine. Note that GT.M does not support concurrent access to the same
database file by multiple versions of the software.
- The format of the RUNDOWN command is:
+ The format of the MUPIP RUNDOWN command is:
RU[NDOWN] {-FILE file-name|-REGION region-list]}
@@ -2413,7 +2499,7 @@
The RUNDOWN command may include one of the following qualifiers:
-F[ile]
- -R[egion]
+ -R[egion]=region-list
If the RUNDOWN command does not specify either -File or -Region, it checks
all the IPC resources (shared memory) on the system and if they are
@@ -2432,9 +2518,16 @@
3 Region
Region
- Specifies that the argument contains one or more region-names that
- identify database files mapped by the current Global Directory. Use the
- wild card "*" to rundown all inactive regions in a global directory.
+ The region-list identifies the target of the RUNDOWN. region-list may
+ specify more than one region of the current global directory in a list.
+ Regions are case-insensitive, separated by a comma, and wildcards can be
+ used to specify them. Any region-name may include the wildcard characters
+ * and % (remember to escape them to protect them from inappropriate
+ expansion by the shell). Any region name expansion occurs in M (ASCII)
+ collation order.
+
+ Use the wildcard "*" to rundown all inactive regions in a global
+ directory.
Incompatible with: -FILE
@@ -2443,6 +2536,18 @@
list of databases, it does not perform any clean up on regions that have
no abandoned memory segments but may not have been shutdown in a crash.
+3 Override
+ Override
+
+ Overrides the protection that prevents MUPIP RUNDOWN from performing a
+ rundown of a replication-enabled (with BEFORE_IMAGE) database or a
+ non-replicated NOBEFORE-journaled database that was abnormally shutdown.
+ The protection involves issuing the MUUSERLBK error for a previously
+ crashed replication-enabled (with BEFORE IMAGE journaling) database and
+ the MUUSERECOV error for a non-replicated or NOBEFORE-journaled database.
+ Both these errors prevent complications related to data recovery from a
+ journal file or a replication-enabled database.
+
2 SET
SET
@@ -2466,6 +2571,7 @@
-JN[LFILE]
-JO[URNAL]=journal-option-list
-L[OCK_SPACE]=integer
+ -M[UTEX_SLOTS]=integer
-[NO]INST[_FREEZE_ON_ERROR]
-PA[RTIAL_RECOV_BYPASS]
-REP[LICATION]={ON|OFF}
@@ -2518,10 +2624,14 @@
file(s) mapped by the current Global Directory. The format of the REGION
qualifier is:
- -R[EGION]
+ -R[EGION]=region-list
- SET -REGION changes multiple files when the parameter contains a list
- and/or wildcards.
+ The region-list identifies the target of SET. region-list may specify more
+ than one region of the current global directory in a list. Regions are
+ case-insensitive, separated by a comma, and wildcards can be used to
+ specify them. Any region-name may include the wildcard characters * and %
+ (remember to escape them to protect them from inappropriate expansion by
+ the shell). Any region name expansion occurs in M (ASCII) collation order.
Incompatible with: -FILE
@@ -2596,6 +2706,19 @@
Instance Freeze. This flag modifies the "Inst Freeze on Error" file header
flag.
+3 Mutex_slots
+ Mutex_slots
+
+ Sets the size of a structure that GT.M uses to manage contention for the
+ principal critical section for a database. Performance issues may occur
+ when there are many processes contending for database access and if this
+ structure cannot accommodate all waiting processes. Therefore, FIS
+ recommends setting this value to a minimum of slightly more than the
+ maximum number of concurrent processes you expect to access the database.
+
+ The minimum value is 64 and the maximum value is 32768. The default value
+ is 1024.
+
3 Journal
Journal
@@ -2718,7 +2841,7 @@
vary in measurement speed and estimate accuracy. The format of the MUPIP
SIZE command is:
- MUPIP SI[ZE] [-h[euristic]=estimation_technique] [-s[elect]=global-name-list] [-r[egion]=region-list]
+ MUPIP SI[ZE] [-h[euristic]=estimation_technique] [-s[elect]=global-name-list] [-r[egion]=region-list] [-a[djacency]=integer]
The optional qualifiers of MUPIP SIZE are:
@@ -2746,6 +2869,9 @@
a negative level from the root of the global tree where -1 means
children of the root.
+ The technique reports the results for levels other than 0 show
+ adjacency for the next lower (one less) level.
+
* arsample,samples=<smpls>
Uses acceptance/rejection sampling of random tree traversals to
@@ -2769,6 +2895,15 @@
In terms of accuracy, MUPIP INTEG -FAST -FULL is the most accurate.
+ -Adjacency=integer
+
+ Specifies the logical adjacency of data blocks that MUPIP SIZE should
+ assume during estimation. By default, MUPIP SIZE assumes -ADJACENCY=10 and
+ reports the logical adjacency in the "Adjacent" column of the MUPIP SIZE
+ report. Note that adjacency is only a proxy for database organization and
+ its usefulness may be limited by the technology and configuration of your
+ secondary storage.
+
-Select
Specifies the global variables on which MUPIP SIZE runs. If -SELECT is not
@@ -2836,6 +2971,28 @@
privileges. To STOP a process belonging to another account, MUPIP STOP
must execute as root.
+ **Caution**
+
+ On receipt of a MUPIP STOP signal, a GT.M process cleans up its
+ participation in managing the database before shutting down. On receipt of
+ three MUPIP STOP signals in a row, a GT.M process shuts down forthwith
+ without cleaning up - the equivalent of a kill -9 signal. This can result
+ in structural database damage, because GT.M does not have sufficient
+ control of what happens in response to an immediate process termination to
+ protect against database damage under all circumstances.
+
+ In all cases, on receipt of a MUPIP STOP, a process will eventually
+ terminate once it gets the resources needed to clean up. Use three MUPIP
+ STOPs in a row only as a last resort, and when you do, perform a MUPIP
+ INTEG at your earliest opportunity thereafter to check for database
+ structural damage, and repair any damage following the procedures in
+ Chapter 11 (Maintaining Database Integrity).
+
+ You may never have to perform a MUPIP STOP if your application is designed
+ in a way that it reduces or eliminates the probability of a process
+ getting in the final try of a transaction. For more information, refer to
+ the Programmers Guide.
+
2 TRIGGER
TRIGGER
@@ -2863,8 +3020,7 @@
-TRIG[GERFILE]=<trigger_definitions_file> [-NOPR[OMPT]]
- o For information on the syntax and usage of a trigger definition file,
- refer to GT.M Programmer's Guide.
+ o
o A MUPIP TRIGGER -TRIGGERFILE operation occurs within a transaction
boundary, therefore, if even one trigger from the trigger definition
file fails to parse correctly, MUPIP TRIGGER rolls back the entire
@@ -2886,6 +3042,12 @@
for all database updates, should be to ensure that you provide the
same value for gtm_chset during load compilation and run-time
compilation.
+ o MUPIP TRIGGER replicate trigger definitions as logical actions from an
+ originating/primary instance to a replicating/secondary instance based
+ on LGTRIG journal records. This permits the instances to have
+ different sets of triggers and differing database layouts (for
+ example, different # of regions, different block sizes, different
+ maximum-record-size, and so on).
o Incompatible with: -SELECT
**Note**
@@ -2923,6 +3085,15 @@
"Cycle" as part of a comment. Cycle is the number of trigger definition
updates (addition, modification, or deletion) performed on a global.
+ **Important**
+
+ MUPIP TRIGGER treats the deletion of a non-existent trigger as a success;
+ if that is the only operation, or one of a set of successful operations,
+ it return success 0 to the shell Also, MUPIP TRIGGER returns failure in
+ case of trigger selection using trigger names where the number after the
+ pound-sign (#) starts with a 0 (which is an impossible auto-generated
+ trigger name).
+
3 Examples
Examples
@@ -3384,7 +3555,7 @@
system. Therefore, ensure that the AUTOSWITCHLIMIT never exceeds the
file-system limit.
- The default value for AUTOSWITCHLIMIT is 8388600 & the maximum value is
+ The default value for AUTOSWITCHLIMIT is 8386560 & the maximum value is
8388607 blocks (4GB-512 bytes). The minimum value for AUTOSWITCHLIMIT is
16384. If the difference between the AUTOSWITCHLIMIT and the allocation
value is not a multiple of the extension value, GT.M rounds-down the value
@@ -4574,7 +4745,7 @@
-RES[YNC]=<journal sequence number>
- Specifies the journal sequence number to which GT.M must rollback the the
+ Specifies the journal sequence number to which GT.M must rollback the
database/journal files need to be rolled back to a specific point. If you
specify a journal sequence number that is greater than the last consistent
state, GT.M rolls back the database/journal files to the last consistent
@@ -4628,8 +4799,8 @@
the begin transaction number of the earliest journal file to be processed
for that region is same as the current transaction in the database file
and that the end transaction number of every journal file is equal to the
- the begin transaction number of the next generation journal file for a
- given region. By default, -FORWARD uses -CHECKTN.
+ begin transaction number of the next generation journal file for a given
+ region. By default, -FORWARD uses -CHECKTN.
-NOCHECKTN forces forward recovery by overriding inbuilt mechanisms for
checking transaction integrity. Use -NOCHECKTN with caution because it may
@@ -4982,6 +5153,7 @@
ZKILL 10\time\tnum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node
ZTWORM 11\time\tnum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\ztwormhole
ZTRIG 12\time\tnum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node
+ LGTRIG 13\time\tnum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\trigdefinition
where:
@@ -5013,6 +5185,9 @@
12 record indicates a ZTRIGGER command.
+ 13 record indicates a trigger definition as a logical action from an
+ originating/primary instance to a replicating/secondary instance
+
Journal extracts contain NULL records only in a multisite replication
configuration where triggers or external M-filters are active. Here are
two examples when NULL records are sent to the journal files:
@@ -5047,17 +5222,19 @@
TZKILL time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node
TZTWORM time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\ztwormhole
TZTRIG time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node
+ TLGTRIG time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\trigdefinition
USET time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node=sarg
UKILL time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node
UZKILL time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node
UZTWORM time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\ztwormhole
UZTRIG time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node
+ ULGTRIG time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\trigdefinition
TCOM time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\partners\tid
INCTN time\tnum\chksum\pid\clntpid\opcode\incdetail
EPOCH time\tnum\chksum\pid\clntpid\jsnum\blks_to_upgrd\free_blocks\total_blks\fully_upgraded[\strm_num\strm_seq]...
PBLK time\tnum\chksum\pid\clntpid\blknum\bsiz\blkhdrtn\ondskbver
AIMG time\tnum\chksum\pid\clntpid\blknum\bsiz\blkhdrtn\ondskbver
- NULL time\tnum\pid\clntpid\jsnum\strm_num\strm_seq
+ NULL time\tnum\chksum\pid\clntpid\jsnum\strm_num\strm_seq
ZTSTART time\tnum\chksum\pid\clntpid\token
FSET time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node=sarg
FKILL time\tnum\chksum\pid\clntpid\token_seq\strm_num\strm_seq\updnum\nodeflags\node
@@ -5147,6 +5324,9 @@
| token_seq | If replication is turned on, it is the journal |
| | sequence number. If not, it is a unique 8-byte token. |
|----------------+-------------------------------------------------------|
+ | trigdefinition | Trigger definition string corresponding to an LGTRIG |
+ | | journal record. |
+ |----------------+-------------------------------------------------------|
| | =n where this is the nth update in the TP or ZTP |
| updnum | transaction. n=1 for the 1st update etc. 0 for |
| | non-TP. |
@@ -5490,6 +5670,9 @@
-log=<log file name> [-log_interval=<integer>]
{-rootprimary|-propagateprimary} [{-updok|-updnotok}]
[-cmplvl=<compression level>]
+ [-tlsid=<label>]
+ [-[no]plaintextfallback]
+ [-renegotiate_interval=<minutes>]
Qualifiers:
@@ -5507,9 +5690,17 @@
-secondary=<hostname:port>
- Identifies the replicating instance. <hostname:port> includes an IP
- address (or a hostname that resolves to an IP address) and the port at
- which the Receiver Server is waiting for a connection.
+ Identifies the replicating instance. <hostname:port> specifies an IPv4 or
+ IPv6 address optionally encapsulated by square-brackets ([]) like
+ "127.0.0.1", "::1", "[127.0.0.1]", or "[::1]" or a hostname that resolves
+ to an IPv4 or IPv6 address and the port at which the Receiver Server is
+ waiting for a connection.
+
+ If, in your environment, the same hostname is used for both IPv4 and IPv6,
+ GT.M defaults to IPv6. If you wish to use IPv4, perhaps because you have a
+ Receiver Server running a pre-V6.0-003 version of GT.M that does not
+ support IPv6, set the environment variable gtm_ipv4_only to "TRUE", "YES",
+ or a non-zero integer in order to force GT.M to use IPv4.
-passive
@@ -5891,6 +6082,46 @@
insufficient authorization), the replication logic logs a DLLNOOPEN error
and continues with no compression.
+ -tlsid=<label>
+
+ Instructs the Source or Receiver Server to use the TLS certificate and
+ private key pairs having <label> as the TLSID in the configuration file
+ pointed to by the gtmcrypt_config environment variable. TLSID is a
+ required parameter if TLS/SSL is to be used to secure replication
+ connection between instances. If private keys are encrypted, an
+ environment variable of the form gtmtls_passwd_<label> specifies their
+ obfuscated password. You can obfuscate passwords using the 'maskpass'
+ utility provided along with the encryption plugin. If you use unencrypted
+ private keys, set the gtmtls_passwd_<label> environment variable to a
+ non-null dummy value; this prevents inappropriate prompting for a
+ password.
+
+ -[NO]PLAINtextfallback
+
+ Specifies whether the replication server is permitted to fallback to
+ plaintext communication. The default is -NOPLAINtextfallback. If
+ NOPLAINTEXTFALLBACK is in effect, GT.M issues a REPLNOTLS error in the
+ event it is unable to establish a TLS connection. [Note: GT.M versions
+ prior to V6.1-000 did not support TLS for replication - if needed it could
+ be implemented with an external application such as stunnel
+ (http://stunnel.org).] If PLAINTEXTFALLBACK is in effect, in the event of
+ a failure to establish a TLS connection, GT.M issues REPLNOTLS as a
+ warning. Once a permitted plaintext replication connection is established
+ for a connection session, GT.M never attempts to switch that connection
+ session to TLS connection.
+
+ -RENEGotiate_interval=<minutes >
+
+ Specifies the time in mintues to wait before attempting to perform a TLS
+ renegotiation. The default -RENEGOTIATE_INTERVAL is a little over 120
+ minutes. A value of zero causes GT.M never to attempt a renegotiation. The
+ MUPIP REPLIC -SOURCE -JNLPOOL -SHOW [-DETAIL] command shows the time at
+ which the next TLS renegotiation is scheduled, and how many such
+ renegotiations have occurred thus far for a given secondary instance
+ connection. As renegotiation requires the replication pipeline to be
+ temporarily flushed, followed by the actual renegotiation, TLS
+ renegotiation can cause momentary spikes in replication backlog.
+
2 Shutdown_Source_Server
Shutdown Source Server
@@ -5932,6 +6163,11 @@
journal records from the Journal Pool and transports them to the system
specified by -secondary.
+ Before activation, -activate sets the Source Server to ACTIVE_REQUESTED
+ mode. On successful activation, GT.M sets the Source Server mode to
+ ACTIVE. GT.M produces an error when there is an attempt to activate a
+ Source Server in ACTIVE_REQUESTED mode.
+
-instsecondary=<instance_name>
Identifies the replicating instance to which the passive Source Server
@@ -5975,6 +6211,11 @@
with which the Source Server is communicating, deactivate the Source
Server and then activate it with a different replicating instance.
+ Before deactivation, -deactivate sets the Source Server to
+ PASSIVE_REQUESTED mode. On successful deactivation, GT.M sets the Source
+ Server mode to PASSIVE. GT.M produces an error when there is an attempt to
+ deactivate a Source Server in PASSIVE_REQUESTED mode.
+
-instsecondary=<instance_name>
Identifies the active Source Server to transition to the passive (standby)
@@ -6004,6 +6245,12 @@
o Specify -stopsourcefilter as an option for starting the Receiver
Server.
+ Note
+
+ If a filter fails to respond within just over a minute to delivery of a
+ mini-transaction or TP transaction, a Source or Receiver Server issues a
+ FILTERTIMEDOUT error, stops the filter, and exits.
+
2 Check_Server_Health
Check Server Health
@@ -6299,6 +6546,7 @@
[-updateresync=</path/to/bkup-orig-repl-inst-file>
{[-resume=<strm_num>|-reuse=<instname>]}
[-initialize] [-cmplvl=n]
+ [-tlsid=<label>]
Qualifiers:
@@ -6306,6 +6554,10 @@
Identifies the Receiver Server.
+ -start
+
+ Starts the Receiver Server and Update Process.
+
-listenport=<port number>
Specifies the TCP port number the Receiver Server will listen to for
@@ -6326,12 +6578,20 @@
considered field test grade functionality as long as that function is
considered field test grade functionality.
+ -log=<recsrv_log_file_name >
+
+ Specifies the location of the log file of the Receiver Server. When -log
+ is specified, the Update Process writes to a log file named
+ <recsrv_log_file_name>.updproc. Note that the name of the Update Process
+ log file name has .updproc at the end to distinguish it from the Receiver
+ Server's log file name.
+
-log_interval="[integer1],[integer2]"
integer1 specifies the number of transactions for which the Receiver
- Server should wait before writing to the log file. integer2 specifies the
+ Server should wait before writing to its log file. integer2 specifies the
number of transactions for which the Update Process should wait before
- writing to the log file. The default logging interval is 1000
+ writing to its log file. The default logging interval is 1000
transactions.
If integer1 or integer2 is 0, the logging interval is set to the default
@@ -6467,6 +6727,20 @@
-resync), which is intended for use under the direction of FIS GT.M
support.
+ -tlsid=<label>
+
+ Instructs the Source or Receiver Server to use the TLS certificate and
+ private key pairs having <label> as the TLSID in the configuration file
+ pointed to by the gtmcrypt_config environment variable. TLSID is a
+ required parameter if TLS/SSL is to be used to secure replication
+ connection between instances. If private keys are encrypted, an
+ environment variable of the form gtmtls_passwd_<label> specifies their
+ obfuscated password. You can obfuscate passwords using the 'maskpass'
+ utility provided along with the encryption plugin. If you use unencrypted
+ private keys, set the gtmtls_passwd_<label> environment variable to a
+ non-null dummy value; this prevents inappropriate prompting for a
+ password.
+
2 Start_Update_Process
Start Update Process
@@ -6667,6 +6941,9 @@
locally). If you do not use -fetchresync, the database rolls back to the
last consistent replicating instance state.
+ A FETCHRESYNC ROLLBACK operation sends its current working directory to
+ the Source Server log.
+
The system stores extracted lost transactions in the file <extract file>
specified by this mandatory qualifier. The starting point for the search
for lost transactions is the JNL_SEQNO obtained from the originating
@@ -7035,7 +7312,7 @@
1 Copyright
Copyright
- Copyright 2013
+ Copyright 2014
Fidelity Information Services, Inc. All rights reserved.
@@ -7056,7 +7333,7 @@
**Note**
- This help file is a concise representation of revision V6.1-000 of the
+ This help file is a concise representation of revision V6.2-000 of the
UNIX Administration and Operations Guide. To obtain a copy of the current
revision, go to www.fis-gtm.com and then click on the User Documentation
tab.
diff --git a/sr_port/mupip_backup.c b/sr_port/mupip_backup.c
index 8dd0d0a..46c377a 100644
--- a/sr_port/mupip_backup.c
+++ b/sr_port/mupip_backup.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -88,7 +88,6 @@
#include "trans_log_name.h"
#include "shmpool.h"
#include "mupip_backup.h"
-#include "gtm_rename.h" /* for cre_jnl_file_intrpt_rename() prototype */
#include "gvcst_protos.h" /* for gvcst_init prototype */
#include "add_inter.h"
#include "gtm_logicals.h"
@@ -123,7 +122,6 @@ GBLREF int4 mubmaxblk;
GBLREF tp_region *grlist;
GBLREF tp_region *halt_ptr;
GBLREF bool in_backup;
-GBLREF bool is_directory;
GBLREF bool mu_ctrly_occurred;
GBLREF bool mu_ctrlc_occurred;
GBLREF bool mubtomag;
@@ -661,7 +659,7 @@ void mupip_backup(void)
util_out_print("!/Cannot create the temporary file in directory !AD for online backup",
TRUE, tempdir_trans.len, tempdir_trans.addr);
gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) status);
- error_condition = status;
+ SET_ERROR_CONDITION(status); /* sets "error_condition" & "severity" */
util_out_print("!/MUPIP cannot start backup with above errors!/", TRUE);
mubclnup(rptr, need_to_del_tempfile);
mupip_exit(status);
@@ -683,7 +681,7 @@ void mupip_backup(void)
status = errno;
util_out_print("!/Error re-opening temporary file created by mkstemp()!/", TRUE);
gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) status);
- error_condition = status;
+ SET_ERROR_CONDITION(status); /* sets "error_condition" & "severity" */
util_out_print("!/MUPIP cannot start backup with above errors!/", TRUE);
mubclnup(rptr, need_to_del_tempfile);
mupip_exit(status);
@@ -725,7 +723,7 @@ void mupip_backup(void)
{
status = errno;
gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) status);
- error_condition = status;
+ SET_ERROR_CONDITION(status); /* sets "error_condition" & "severity" */
util_out_print("!/MUPIP cannot start backup with above errors!/", TRUE);
mubclnup(rptr, need_to_del_tempfile);
mupip_exit(status);
@@ -845,8 +843,8 @@ void mupip_backup(void)
MEMCPY_LIT(reg->rname, JNLPOOL_DUMMY_REG_NAME);
reg->rname_len = STR_LIT_LEN(JNLPOOL_DUMMY_REG_NAME);
reg->rname[reg->rname_len] = '\0';
- if (!repl_inst_get_name(instfilename, &full_len, MAX_FN_LEN + 1, issue_rts_error))
- GTMASSERT; /* rts_error should have been issued by repl_inst_get_name */
+ assertpro(repl_inst_get_name(instfilename, &full_len, MAX_FN_LEN + 1, issue_rts_error));
+ /* rts_error should have been issued by repl_inst_get_name in case of 0 return */
udi = FILE_INFO(reg);
seg = reg->dyn.addr;
memcpy((char *)seg->fname, instfilename, full_len);
@@ -1121,8 +1119,7 @@ repl_inst_bkup_done1:
assert(!pool_init || (INVALID_SHMID != shm_id));
if (INVALID_SHMID != shm_id)
{
- if (INVALID_SEMID == sem_id)
- GTMASSERT; /* out-of-design situation */
+ assertpro(INVALID_SEMID != sem_id); /* out-of-design situation */
/* The journal pool exists. Note down the journal seqno from there and copy that onto the backed up
* instance file header. Also, clean up other fields in the backed up instance file header.
*/
@@ -1233,8 +1230,7 @@ repl_inst_bkup_done2:
if (udi->grabbed_access_sem)
{
assert(holds_sem[SOURCE][JNL_POOL_ACCESS_SEM] && (INVALID_SEMID != sem_id));
- if (SS_NORMAL != rel_sem_immediate(SOURCE, JNL_POOL_ACCESS_SEM))
- GTMASSERT;
+ assertpro(SS_NORMAL == rel_sem_immediate(SOURCE, JNL_POOL_ACCESS_SEM));
}
if (udi->grabbed_ftok_sem)
ftok_sem_release(jnlpool.jnlpool_dummy_reg, decr_cnt, TRUE);
@@ -1312,7 +1308,7 @@ repl_inst_bkup_done2:
if (newjnlfiles)
{
if (cs_data->jnl_file_len)
- cre_jnl_file_intrpt_rename(((int)cs_data->jnl_file_len), cs_data->jnl_file_name);
+ cre_jnl_file_intrpt_rename(cs_addrs);
if (JNL_ALLOWED(cs_data))
{
memset(&jnl_info, 0, SIZEOF(jnl_info));
diff --git a/sr_port/mupip_create.c b/sr_port/mupip_create.c
index 86ad86b..f8a35c4 100644
--- a/sr_port/mupip_create.c
+++ b/sr_port/mupip_create.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -27,20 +27,22 @@
#include "mupip_exit.h"
#include "mupip_create.h"
#include "mu_cre_file.h"
+#include "gtmmsg.h"
GBLREF gd_addr *gd_header;
GBLREF gd_region *gv_cur_region;
+error_def(ERR_DBNOCRE);
+error_def(ERR_MUPCLIERR);
+error_def(ERR_NOREGION);
+
void mupip_create(void)
{
- bool found;
+ boolean_t found;
char buff[MAX_RN_LEN + 1], create_stat, exit_stat;
- unsigned short reglen;
- int i;
gd_region *reg, *reg_top;
-
- error_def(ERR_MUPCLIERR);
- error_def(ERR_DBNOCRE);
+ int i;
+ unsigned short reglen;
exit_stat = EXIT_NRM;
gvinit();
@@ -49,9 +51,9 @@ void mupip_create(void)
reglen = SIZEOF(buff);
if (0 == cli_get_str("REGION", buff, ®len))
mupip_exit(ERR_MUPCLIERR);
- for (i=0; (MAX_RN_LEN + 1 > i) && (' ' != buff[i]); i++)
+ for (i=0; i < reglen; i++)
buff[i] = TOUPPER(buff[i]); /* ensure uppercase to match gde conventions */
- for ( ; MAX_RN_LEN + 1 > i; i++)
+ for ( ; ARRAYSIZE(buff) > i; i++)
buff[i] = 0;
found = FALSE;
for (reg = gd_header->regions, reg_top = reg + gd_header->n_regions; reg < reg_top; reg++)
@@ -64,7 +66,7 @@ void mupip_create(void)
}
if (FALSE == found)
{
- util_out_print("Error: region not found.",TRUE);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOREGION, 2, reglen, buff);
mupip_exit(ERR_MUPCLIERR);
}
gv_cur_region = reg;
diff --git a/sr_port/mupip_integ.c b/sr_port/mupip_integ.c
index 1cadd70..72083de 100644
--- a/sr_port/mupip_integ.c
+++ b/sr_port/mupip_integ.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -17,6 +17,7 @@
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
+#include "gdsblk.h"
#include "gdsfhead.h"
#include "error.h"
#include "cli.h"
@@ -54,7 +55,6 @@
#define MAX_UTIL_LEN 80
#define APPROX_ALL_ERRORS 1000000
#define DEFAULT_ERR_LIMIT 10
-#define DEFAULT_ADJACENCY 10
#define PERCENT_FACTOR 100
#define PERCENT_DECIMAL_SCALE 100000
#define PERCENT_SCALE_FACTOR 1000
@@ -185,6 +185,7 @@ void mupip_integ(void)
uint4 cli_status;
block_id dir_root, mu_index_adj, mu_data_adj, muint_block;
uint4 prev_errknt, mu_dir_blks, mu_dir_recs, mu_data_blks, mu_data_recs, mu_index_blks, mu_index_recs;
+ uint4 tot_blks;
qw_num mu_dir_size, mu_index_size, mu_data_size;
tp_region *rptr;
file_control *fc;
@@ -198,9 +199,6 @@ void mupip_integ(void)
span_node_integ span_node_data;
sndata = &span_node_data;
- sndata->sn_cnt = 0;
- sndata->sn_blk_cnt = 0;
- sndata->sn_type = SN_NOT;
error_mupip = FALSE;
if (NULL == gv_target)
gv_target = (gv_namehead *)targ_alloc(DUMMY_GLOBAL_VARIABLE_LEN, NULL, NULL);
@@ -351,7 +349,7 @@ void mupip_integ(void)
mu_data_blks = mu_data_recs = 0;
mu_index_blks = mu_index_recs = 0;
mu_int_err_ranges = (CLI_NEGATED != cli_present("KEYRANGES"));
- mu_int_root_level = (unsigned char)-1;
+ mu_int_root_level = BML_LEVL; /* start with what is an invalid level for a root block */
mu_map_errs = 0, prev_errknt = 0, largest_tn = 0;
mu_int_blks_to_upgrd = 0;
for (idx = 0; idx <= MAX_BT_DEPTH; idx++)
@@ -363,6 +361,9 @@ void mupip_integ(void)
mu_int_offset[0] = 0;
mu_int_plen = 1;
memset(mu_int_adj, 0, SIZEOF(mu_int_adj));
+ sndata->sn_cnt = 0;
+ sndata->sn_blk_cnt = 0;
+ sndata->sn_type = SN_NOT;
if (region)
{
util_out_print("!/!/Integ of region !AD", TRUE, REG_LEN_STR(rptr->reg));
@@ -530,8 +531,8 @@ void mupip_integ(void)
for (idx = mu_int_root_level; idx >= 0; idx--)
{
if ((0 == idx) && muint_fast && (trees->root != dir_root))
- util_out_print("!5UL !12UL NA NA NA", TRUE,
- idx, mu_int_blks[idx]);
+ util_out_print("!5UL !12UL NA NA !12UL", TRUE,
+ idx, mu_int_blks[idx], mu_int_adj[idx]);
else
{
QWPERCENTCALC(leftpt, rightpt, mu_int_size[idx], mu_int_blks[idx],
@@ -654,7 +655,7 @@ void mupip_integ(void)
util_out_print("Index !12UL !12UL !8UL.!3ZL !12UL", TRUE, mu_index_blks, mu_index_recs, leftpt, rightpt,
mu_index_adj);
if (muint_fast)
- util_out_print("Data !12UL NA NA NA", TRUE, mu_data_blks);
+ util_out_print("Data !12UL NA NA !12UL", TRUE, mu_data_blks, mu_data_adj);
else
{
QWPERCENTCALC(leftpt, rightpt, mu_data_size, mu_data_blks, mu_int_data.blk_size);
@@ -662,24 +663,22 @@ void mupip_integ(void)
leftpt, rightpt, mu_data_adj);
}
if ((FALSE == block) && (MUINTKEY_FALSE == muint_key))
+ {
util_out_print("Free !12UL NA NA NA", TRUE,
mu_int_data.trans_hist.total_blks -
(mu_int_data.trans_hist.total_blks + mu_int_data.bplmap - 1) / mu_int_data.bplmap -
mu_data_blks - mu_index_blks - mu_dir_blks);
+ tot_blks = mu_int_data.trans_hist.total_blks
+ - (mu_int_data.trans_hist.total_blks + mu_int_data.bplmap - 1) / mu_int_data.bplmap;
+ } else
+ tot_blks = mu_data_blks + mu_index_blks + mu_dir_blks;
if (muint_fast)
- {
util_out_print("Total !12UL NA NA !12UL", TRUE,
- mu_int_data.trans_hist.total_blks -
- (mu_int_data.trans_hist.total_blks + mu_int_data.bplmap - 1) / mu_int_data.bplmap,
- mu_data_adj + mu_index_adj);
- } else
- {
+ tot_blks, mu_data_adj + mu_index_adj);
+ else
util_out_print("Total !12UL !12UL NA !12UL", TRUE,
- mu_int_data.trans_hist.total_blks -
- (mu_int_data.trans_hist.total_blks + mu_int_data.bplmap - 1) / mu_int_data.bplmap,
- mu_dir_recs + mu_index_recs + mu_data_recs, mu_data_adj + mu_index_adj);
- }
- if(sndata->sn_cnt)
+ tot_blks, mu_dir_recs + mu_index_recs + mu_data_recs, mu_data_adj + mu_index_adj);
+ if (sndata->sn_cnt)
{
util_out_print("[Spanning Nodes:!UL ; Blocks:!UL]", TRUE, sndata->sn_cnt, sndata->sn_blk_cnt);
/*[span_node:<no of span-node in DB>; blks: <total number of spanning blocks used by all span-node>]*/
diff --git a/sr_port/mupip_io_dev_dispatch.h b/sr_port/mupip_io_dev_dispatch.h
index a08ac3a..cbf40a8 100644
--- a/sr_port/mupip_io_dev_dispatch.h
+++ b/sr_port/mupip_io_dev_dispatch.h
@@ -1,13 +1,13 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
-****************************************************************/
+ ****************************************************************/
/* io_dev_dispatch.h is a superset of this file which includes those needed by GT.M
* so, if you need to make a change here, please keep the other one in sync.
@@ -26,7 +26,7 @@ UNIX_ONLY(GBLDEF) VMS_ONLY(LITDEF) dev_dispatch_struct io_dev_dispatch_mupip[] =
# endif
ionil_dev,
# ifdef UNIX
- iotype(iorm, iorm, iopi, nil),
+ iotype(iorm, iorm, iopi, iopi),
# else
iotype(iorm, iorm, nil, nil),
# endif
diff --git a/sr_port/mupip_recover.c b/sr_port/mupip_recover.c
index 572d7b1..78c4c05 100644
--- a/sr_port/mupip_recover.c
+++ b/sr_port/mupip_recover.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -214,6 +214,8 @@ void mupip_recover(void)
mur_get_options();
/*DEFER_INTERRUPTS(INTRPT_IN_MUR_OPEN_FILES); */
mur_open_files_status = mur_open_files();
+ if (WBTEST_ENABLED(WBTEST_KILL_ROLLBACK))
+ kill(getpid(), SIGKILL);
jgbl.mur_extract = mur_options.extr[GOOD_TN]; /* journal extract process */
/*ENABLE_INTERRUPTS(INTRPT_IN_MUR_OPEN_FILES);*/
if (!mur_open_files_status) /* mur_open_files already issued error */
@@ -265,7 +267,7 @@ void mupip_recover(void)
{
TREF(jnl_extract_nocol) = !mur_options.update && jgbl.mur_extract && TREF(jnl_extract_nocol);
if (db_absent)
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_DBCOLLREQ, 4, LEN_AND_LIT("Mising Database file"),
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_DBCOLLREQ, 4, LEN_AND_LIT("Missing Database file"),
DB_LEN_STR(db_absent_rctl->gd));
else
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_DBCOLLREQ, 4, LEN_AND_LIT("Instance is frozen."),
diff --git a/sr_port/mupip_set_journal.c b/sr_port/mupip_set_journal.c
index d02d7b8..4f44173 100644
--- a/sr_port/mupip_set_journal.c
+++ b/sr_port/mupip_set_journal.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -52,7 +52,6 @@
#include "tp_change_reg.h"
#include "gtm_file_stat.h"
#include "min_max.h" /* for MAX and JNL_MAX_RECLEN macro */
-#include "gtm_rename.h" /* for cre_jnl_file_intrpt_rename() prototype */
#include "send_msg.h"
#include "gtmio.h"
#include "is_file_identical.h"
@@ -133,7 +132,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn)
jnl_file_header header;
int4 status1;
uint4 status2;
- boolean_t header_is_usable = FALSE;
+ boolean_t header_is_usable = FALSE, noprevlink_requested;
# endif
boolean_t jnl_buffer_updated = FALSE, jnl_buffer_invalid = FALSE;
int jnl_buffer_size;
@@ -146,7 +145,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn)
if (!mupip_set_journal_parse(&jnl_options, &jnl_info))
{
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_MUPCLIERR);
- error_condition = ERR_MUPCLIERR;
+ SET_ERROR_CONDITION(ERR_MUPCLIERR); /* sets "error_condition" & "severity" */
return ERR_MUPCLIERR;
}
if (region && (NULL == grlist))
@@ -442,7 +441,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn)
jnl_info.prev_jnl = (char *)prev_jnl_fn;
jnl_info.prev_jnl_len = 0;
if (csd->jnl_file_len)
- cre_jnl_file_intrpt_rename(((int)csd->jnl_file_len), csd->jnl_file_name);
+ cre_jnl_file_intrpt_rename(cs_addrs);
assert(0 == csd->jnl_file_len || 0 == csd->jnl_file_name[csd->jnl_file_len]);
csd->jnl_file_name[csd->jnl_file_len] = 0;
if (!jnl_options.filename_specified)
@@ -526,7 +525,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn)
break;
}
jnlname_same = ((jnl_info.jnl_len == csd->jnl_file_len)
- && (0 == memcmp(jnl_info.jnl, csd->jnl_file_name, jnl_info.jnl_len))) ? TRUE : FALSE;
+ && (0 == memcmp(jnl_info.jnl, csd->jnl_file_name, jnl_info.jnl_len))) ? TRUE : FALSE;
jnlfile.addr = (char *)csd->jnl_file_name;
jnlfile.len = csd->jnl_file_len;
if (!jnlname_same)
@@ -589,11 +588,12 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn)
* common journal file name. Also this way we disallow switching to a user-specified new
* journal file that already exists (say the database file itself due to a command line typo).
*/
- if (FILE_PRESENT & curr_stat_res)
+ noprevlink_requested = (CLI_NEGATED == cli_present("PREVJNLFILE"));
+ if ((FILE_PRESENT & curr_stat_res) && !noprevlink_requested)
{
keep_prev_link = jnl_points_to_db;
safe_to_switch = (jnlname_same && keep_prev_link);
- } else if (FILE_PRESENT & new_stat_res)
+ } else if ((FILE_PRESENT & new_stat_res) && !noprevlink_requested)
{
keep_prev_link = FALSE;
/* In this case, the current jnl file does not exist. And so the prevlinks are
@@ -629,8 +629,15 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn)
curr_jnl_present = (FILE_PRESENT & curr_stat_res) ? TRUE : FALSE;
if (curr_jnl_present)
{
- if (FILE_READONLY & curr_stat_res)
- {
+ if ((FILE_READONLY & curr_stat_res) && (((NULL != cs_addrs->nl)
+ && (0 != cs_addrs->nl->jnl_file.u.inode))
+ || jnlname_same))
+ { /* Current journal file is read-only and a) it is open by another process in the
+ * shared memory. We do not want to interfere until it is properly terminated by the
+ * process who uses it b) new and old journal names are the same (e.g. one did not
+ * specify -journal="filename" in the command line). Such an attempt will rename the
+ * current journal file. We don't want renaming for the read-only files.
+ */
gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_JNLRDONLY, 2,
JNL_LEN_STR(csd));
if (newjnlfiles)
diff --git a/sr_port/mupipbckup.h b/sr_port/mupipbckup.h
index de01d42..b8c7ccb 100644
--- a/sr_port/mupipbckup.h
+++ b/sr_port/mupipbckup.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -110,10 +110,6 @@ typedef struct backup_reg_list_struct
LITREF mval mu_bin_datefmt;
boolean_t backup_block(sgmnt_addrs *csa, block_id blk, cache_rec_ptr_t backup_cr, sm_uc_ptr_t backup_blk_p);
-bool mubfilcpy(backup_reg_list *list);
-bool mubgetfil(backup_reg_list *list, char *name, unsigned short len);
-bool mubinccpy(backup_reg_list *list);
-bool mubgetfil(backup_reg_list *list, char *name, unsigned short len);
boolean_t backup_buffer_flush(gd_region *reg);
void mubclnup(backup_reg_list *curr_ptr, clnup_stage stage);
#ifdef VMS
@@ -123,7 +119,9 @@ void mubexpfilnam(char *dirname, unsigned int dirlen, backup_reg_list *list);
#else
#error Unsupported Platform
#endif
-gd_region *mubfndreg(unsigned char *regbuf, unsigned short len);
+bool mubfilcpy(backup_reg_list *list);
+boolean_t mubgetfil(backup_reg_list *list, char *name, unsigned short len);
+bool mubinccpy(backup_reg_list *list);
void mup_bak_mag(void);
void mup_bak_pause(void);
diff --git a/sr_port/muprec.h b/sr_port/muprec.h
index ba06666..3d4465c 100644
--- a/sr_port/muprec.h
+++ b/sr_port/muprec.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,7 +13,7 @@
#define MUPREC_H_INCLUDED
#include "muprecsp.h" /* non-portable interface prototype */
-
+#include "mu_interactive.h"
#include "jnl_typedef.h" /* for IS_VALID_JRECTYPE macro */
#if defined(UNIX)
@@ -22,8 +22,8 @@
#include "op.h" /* for dollarh function */
#endif
-#define JNL_EXTR_LABEL "GDSJEX06" /* format of the simple journal extract */
-#define JNL_DET_EXTR_LABEL "GDSJDX06" /* format of the detailed journal extract */
+#define JNL_EXTR_LABEL "GDSJEX07" /* format of the simple journal extract */
+#define JNL_DET_EXTR_LABEL "GDSJDX07" /* format of the detailed journal extract */
error_def(ERR_MUINFOSTR);
error_def(ERR_MUINFOUINT6);
@@ -986,7 +986,8 @@ typedef struct onln_rlbk_reg_list_struct
} \
}
-#define MUR_WITHIN_ERROR_LIMIT(err_cnt, error_limit) ((++err_cnt <= error_limit) || (mur_options.interactive && mur_interactive()))
+#define MUR_WITHIN_ERROR_LIMIT(err_cnt, error_limit) ((++err_cnt <= error_limit) || (mur_options.interactive && \
+ mu_interactive("Recovery terminated by operator")))
#ifdef DEBUG
# define MUR_DBG_SET_LAST_PROCESSED_JNL_SEQNO(TOKEN, RCTL) \
@@ -1120,7 +1121,6 @@ void mur_free(void);
void mur_rctl_desc_alloc(reg_ctl_list *rctl);
void mur_rctl_desc_free(reg_ctl_list *rctl);
boolean_t mur_insert_prev(jnl_ctl_list **jjctl);
-boolean_t mur_interactive(void);
boolean_t mur_jctl_from_next_gen(void);
void mur_multi_rehash(void);
uint4 mur_next(jnl_ctl_list *jctl, off_jnl_t dskaddr);
diff --git a/sr_port/mur_back_process.c b/sr_port/mur_back_process.c
index 297249f..0061e6e 100644
--- a/sr_port/mur_back_process.c
+++ b/sr_port/mur_back_process.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -394,11 +394,12 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
rec_token_seq = GET_JNL_SEQNO(jnlrec);
MUR_BACK_PROCESS_ERROR_STR(jctl, jjctl, s);
}
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype))
{
keystr = (jnl_string *)&jnlrec->jrec_set_kill.mumps_node;
- /* Assert that ZTWORMHOLE type record too has same layout as KILL/SET */
+ /* Assert that ZTWORMHOLE and LGTRIG type records have same layout as KILL/SET */
assert((sm_uc_ptr_t)keystr == (sm_uc_ptr_t)&jnlrec->jrec_ztworm.ztworm_str);
+ assert((sm_uc_ptr_t)keystr == (sm_uc_ptr_t)&jnlrec->jrec_lgtrig.lgtrig_str);
# ifdef GTM_CRYPT
if (jctl->jfh->is_encrypted)
{
@@ -418,8 +419,14 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
if (MAX_ZTWORMHOLE_SIZE < keystr->length)
MUR_BACK_PROCESS_ERROR(jctl, jjctl, "ZTWORMHOLE size check failed");
# endif
+ } else if (IS_LGTRIG(rectype))
+ { /* LGTRIG type */
+# ifdef GTM_TRIGGER
+ if (MAX_LGTRIG_LEN < keystr->length)
+ MUR_BACK_PROCESS_ERROR(jctl, jjctl, "LGTRIG size check failed");
+# endif
} else
- { /* SET or KILL type */
+ { /* SET or KILL or ZTRIG type */
if (keystr->length > max_key_size)
MUR_BACK_PROCESS_ERROR(jctl, jjctl, "Key size check failed");
if (0 != keystr->text[keystr->length - 1])
@@ -493,8 +500,8 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
*/
if (REC_HAS_TOKEN_SEQ(rectype))
{
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype) || IS_COM(rectype) || (JRT_EPOCH == (rectype))
- || (JRT_EOF == (rectype)) || (JRT_NULL == (rectype)));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype) || IS_COM(rectype)
+ || (JRT_EPOCH == (rectype)) || (JRT_EOF == (rectype)) || (JRT_NULL == (rectype)));
assert(&jnlrec->jrec_set_kill.token_seq == (token_seq_t *)&jnlrec->jrec_epoch.jnl_seqno);
assert(&jnlrec->jrec_set_kill.token_seq == (token_seq_t *)&jnlrec->jrec_eof.jnl_seqno);
assert(&jnlrec->jrec_set_kill.token_seq == (token_seq_t *)&jnlrec->jrec_null.jnl_seqno);
@@ -510,7 +517,7 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
*/
if (murgbl.resync_strm_seqno_nonzero && IS_REPLICATED(rectype))
{
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype) || IS_COM(rectype)
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype) || IS_COM(rectype)
|| (JRT_NULL == (rectype)));
assert(&jnlrec->jrec_set_kill.strm_seqno == &jnlrec->jrec_null.strm_seqno);
assert(&jnlrec->jrec_tcom.strm_seqno == &jnlrec->jrec_null.strm_seqno);
@@ -620,7 +627,8 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)
{
strm_seqno = jnlrec->jrec_epoch.strm_seqno[idx];
- if (strm_seqno > murgbl.resync_strm_seqno[idx])
+ if (murgbl.resync_strm_seqno[idx]
+ && (strm_seqno > murgbl.resync_strm_seqno[idx]))
{
reached_trnarnd = FALSE;
break;
@@ -660,7 +668,7 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
rec_fence = GET_REC_FENCE_TYPE(rectype);
VMS_MUR_BACK_PROCESS_GET_IMAGE_COUNT(jctl, jnlrec, jjctl, rec_image_count, status);
assert(token == ((struct_jrec_upd *)jnlrec)->token_seq.token);
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype)) /* TUPD/UUPD/FUPD/GUPD */
+ if (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype)) /* TUPD/UUPD/FUPD/GUPD */
{
if (NULL != (multi = MUR_TOKEN_LOOKUP(token, rec_image_count, rec_time, rec_fence)))
{
@@ -722,7 +730,7 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
assert(!murgbl.resync_strm_seqno_nonzero || !mur_options.forward);
if (!skip_rec && murgbl.resync_strm_seqno_nonzero)
{
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype) || (JRT_NULL == (rectype)));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype) || (JRT_NULL == (rectype)));
assert(&jnlrec->jrec_set_kill.strm_seqno == &jnlrec->jrec_null.strm_seqno);
/* strm_seqno & strm_idx have already been initialized before for this record.
* Assert that (i.e. they have not been changed since then) before using them.
@@ -802,7 +810,8 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)
{
strm_seqno = jnlrec->jrec_epoch.strm_seqno[idx];
- if (strm_seqno > murgbl.resync_strm_seqno[idx])
+ if (murgbl.resync_strm_seqno[idx]
+ && (strm_seqno > murgbl.resync_strm_seqno[idx]))
{
reached_trnarnd = FALSE;
break;
@@ -840,8 +849,7 @@ uint4 mur_back_processing_one_region(mur_back_opt_t *mur_back_options)
}
/* for mur_options.forward ERR_JNLREADBOF is not error but others are */
}
- if (!mur_options.forward && (NULL == rctl->jctl_turn_around))
- GTMASSERT;
+ assertpro(mur_options.forward || (NULL != rctl->jctl_turn_around));
return SS_NORMAL;
}
diff --git a/sr_port/mur_close_files.c b/sr_port/mur_close_files.c
index adbfe7b..cf9041a 100644
--- a/sr_port/mur_close_files.c
+++ b/sr_port/mur_close_files.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -145,6 +145,7 @@ boolean_t mur_close_files(void)
repl_inst_hdr_ptr_t inst_hdr = NULL;
seq_num max_strm_seqno[MAX_SUPPL_STRMS], this_strm_seqno;
boolean_t incr_jnlpool_rlbk_cycle = TRUE, got_ftok, anticipatory_freeze_available, was_crit;
+ boolean_t inst_frozen = FALSE;
gtmsource_local_ptr_t gtmsourcelocal_ptr;
global_latch_t *latch;
seq_num max_zqgblmod_seqno = 0, last_histinfo_seqno;
@@ -172,7 +173,7 @@ boolean_t mur_close_files(void)
# ifdef UNIX
if (mur_options.rollback)
memset(&max_strm_seqno[0], 0, SIZEOF(max_strm_seqno));
- anticipatory_freeze_available = ANTICIPATORY_FREEZE_AVAILABLE;
+ anticipatory_freeze_available = INST_FREEZE_ON_ERROR_POLICY;
inst_hdr = jnlpool.repl_inst_filehdr;
/* Note that murgbl.consist_jnl_seqno is maintained even if the only thing done by rollback was lost transaction processing.
* In this case, we shouldn't consider the instance as being rolled back. So, set murgbl.incr_db_rlbkd_cycle = FALSE;
@@ -701,13 +702,13 @@ boolean_t mur_close_files(void)
reg = rctl->gd;
if (NULL == reg)
continue;
+ udi = (NULL != reg->dyn.addr->file_cntl) ? FILE_INFO(reg) : NULL;
if (reg->open)
{
assert(!mur_options.forward); /* for forward recovery, gds_rundown should have been done before */
gv_cur_region = reg;
TP_CHANGE_REG(reg);
assert(!jgbl.onlnrlbk || (cs_addrs->now_crit && cs_addrs->hold_onto_crit) || !murgbl.clean_exit);
- DEBUG_ONLY(udi = FILE_INFO(reg));
assert(!rctl->standalone || (1 == (semval = semctl(udi->semid, 0, GETVAL))));
UNIX_ONLY(rundown_status =) gds_rundown(); /* does the final rel_crit */
if (EXIT_NRM != rundown_status)
@@ -721,7 +722,8 @@ boolean_t mur_close_files(void)
*/
assert(!mur_options.update || rctl->standalone || !murgbl.clean_exit);
if (rctl->standalone UNIX_ONLY(&& EXIT_NRM == rundown_status))
- if (!db_ipcs_reset(reg))
+ /* Avoid db_ipcs_reset if gds_rundown did not remove shared memory */
+ if ((NULL != udi) && !udi->new_shm && !db_ipcs_reset(reg))
wrn_count++;
rctl->standalone = FALSE;
rctl->gd = NULL;
@@ -766,6 +768,8 @@ boolean_t mur_close_files(void)
* an assert to validate our understanding and has no implications in PRO
*/
assert(INVALID_SHMID == repl_instance.recvpool_shmid || jgbl.onlnrlbk);
+ /* Check frozen state before detaching the journal pool */
+ inst_frozen = IS_REPL_INST_FROZEN;
/* Ensure that no new processes have attached to the journal pool */
if (-1 == shmctl(repl_instance.jnlpool_shmid, IPC_STAT, &shm_buf))
{
@@ -788,7 +792,7 @@ boolean_t mur_close_files(void)
jnlpool.gtmsource_local_array = NULL;
jnlpool.jnldata_base = NULL;
jnlpool.repl_inst_filehdr = NULL;
- if (1 == shm_buf.shm_nattch)
+ if ((1 == shm_buf.shm_nattch) && !inst_frozen)
{ /* We are the only one attached. Go ahead and remove the shared memory ID and invalidate it in the
* instance file header as well.
*/
@@ -832,9 +836,9 @@ boolean_t mur_close_files(void)
if (got_ftok)
ftok_sem_release(jnlpool.jnlpool_dummy_reg, FALSE, TRUE); /* immediate=TRUE */
ASSERT_DONOT_HOLD_REPLPOOL_SEMS;
- assert(jgbl.onlnrlbk ||
+ assert(jgbl.onlnrlbk || inst_frozen ||
((INVALID_SEMID == repl_instance.jnlpool_semid) && (0 == repl_instance.jnlpool_semid_ctime)));
- assert(jgbl.onlnrlbk ||
+ assert(jgbl.onlnrlbk || inst_frozen ||
((INVALID_SEMID == repl_instance.recvpool_semid) && (0 == repl_instance.recvpool_semid_ctime)));
repl_inst_write(udi->fn, (off_t)0, (sm_uc_ptr_t)&repl_instance, SIZEOF(repl_inst_hdr));
/* Now that the standalone access is released, we should decrement the counter in the ftok semaphore obtained in
@@ -877,6 +881,7 @@ boolean_t mur_close_files(void)
|| (WBTEST_JNL_FILE_OPEN_FAIL == gtm_white_box_test_case_number)
|| (WBTEST_JNL_CREATE_FAIL == gtm_white_box_test_case_number)
|| (WBTEST_RECOVER_ENOSPC == gtm_white_box_test_case_number)
+ || (WBTEST_FAIL_ON_SHMGET == gtm_white_box_test_case_number)
|| (WBTEST_WCS_FLU_FAIL == gtm_white_box_test_case_number)));
assert(!murgbl.clean_exit);
if (murgbl.wrn_count)
diff --git a/sr_port/mur_db_files_from_jnllist.c b/sr_port/mur_db_files_from_jnllist.c
index 77a9094..e98dbb4 100644
--- a/sr_port/mur_db_files_from_jnllist.c
+++ b/sr_port/mur_db_files_from_jnllist.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2010 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,11 +42,14 @@
#include "iosp.h"
#include "gtmio.h"
#include "gtmmsg.h"
-#include "gtm_rename.h"
GBLREF gd_region *gv_cur_region;
GBLREF gd_addr *gd_header;
+error_def(ERR_JNLREAD);
+error_def(ERR_PREMATEOF);
+error_def(ERR_FILEPARSE);
+
gld_dbname_list *mur_db_files_from_jnllist(char *jnl_file_list, unsigned short jnl_file_list_len, int *db_total)
{
gd_region *reg, *reg_start, *reg_top;
@@ -61,9 +64,6 @@ gld_dbname_list *mur_db_files_from_jnllist(char *jnl_file_list, unsigned short j
#if defined(VMS)
io_status_block_disk iosb;
#endif
- error_def(ERR_JNLREAD);
- error_def(ERR_PREMATEOF);
- error_def(ERR_FILEPARSE);
db_tot = 0;
tdblist = head.next = NULL;
@@ -88,7 +88,7 @@ gld_dbname_list *mur_db_files_from_jnllist(char *jnl_file_list, unsigned short j
if (!get_full_path((char *)seg->fname, (unsigned int)seg->fname_len,
(char *)&db_fname[0], &db_fname_len, MAX_FN_LEN, &ustatus))
{
- gtm_putmsg(VARLSTCNT(5) ERR_FILEPARSE, 2, seg->fname, seg->fname_len, ustatus);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, seg->fname, seg->fname_len, ustatus);
return NULL;
}
assert(db_fname_len);
@@ -106,13 +106,10 @@ gld_dbname_list *mur_db_files_from_jnllist(char *jnl_file_list, unsigned short j
if (!get_full_path(cptr_last, (unsigned int)(cptr - cptr_last),
(char *)jctl->jnl_fn, &jctl->jnl_fn_len, MAX_FN_LEN, &ustatus))
{
- gtm_putmsg(VARLSTCNT(5) ERR_FILEPARSE, 2, cptr_last, cptr - cptr_last, ustatus);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, cptr_last, cptr - cptr_last, ustatus);
return NULL;
}
cptr++; /* skip separator */
- /* Followings fix file name if system crashed during rename
- * (directly related to cre_jnl_file_common) */
- cre_jnl_file_intrpt_rename(jctl->jnl_fn_len, jctl->jnl_fn);
if (!mur_fopen_sp(jctl))
return NULL;
jctl->jfh = (jnl_file_header *)malloc(REAL_JNL_HDR_LEN);
@@ -120,7 +117,7 @@ gld_dbname_list *mur_db_files_from_jnllist(char *jnl_file_list, unsigned short j
DO_FILE_READ(jctl->channel, 0, jfh, REAL_JNL_HDR_LEN, jctl->status, jctl->status2);
if (SS_NORMAL != jctl->status) /* read fails */
{
- gtm_putmsg(VARLSTCNT(6) ERR_JNLREAD, 3, jctl->jnl_fn_len, jctl->jnl_fn, 0, jctl->status);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_JNLREAD, 3, jctl->jnl_fn_len, jctl->jnl_fn, 0, jctl->status);
/* should we do mur_fclose(jctl) here ? */
return NULL;
}
diff --git a/sr_port/mur_forward.c b/sr_port/mur_forward.c
index 9da42b3..bf78597 100644
--- a/sr_port/mur_forward.c
+++ b/sr_port/mur_forward.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -78,7 +78,6 @@ static void (* const extraction_routine[])() =
uint4 mur_forward(jnl_tm_t min_broken_time, seq_num min_broken_seqno, seq_num losttn_seqno)
{
boolean_t added, this_reg_stuck;
- boolean_t is_set_kill_zkill_ztworm, is_set_kill_zkill;
jnl_record *rec;
enum jnl_record_type rectype;
enum rec_fence_type rec_fence;
@@ -291,14 +290,16 @@ uint4 mur_forward(jnl_tm_t min_broken_time, seq_num min_broken_seqno, seq_num lo
rectype = (enum jnl_record_type)rec->prefix.jrec_type;
if (IS_TP(rectype) && IS_TUPD(rectype))
{
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype));
assert(&rec->jrec_set_kill.num_participants == &rec->jrec_ztworm.num_participants);
+ assert(&rec->jrec_set_kill.num_participants == &rec->jrec_lgtrig.num_participants);
num_partners = rec->jrec_set_kill.num_participants;
assert(0 < num_partners);
if (1 < num_partners)
{
this_reg_stuck = TRUE;
assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
+ assert(&rec->jrec_set_kill.update_num == &rec->jrec_lgtrig.update_num);
}
}
}
diff --git a/sr_port/mur_forward_play_cur_jrec.c b/sr_port/mur_forward_play_cur_jrec.c
index d61d67b..f88590b 100644
--- a/sr_port/mur_forward_play_cur_jrec.c
+++ b/sr_port/mur_forward_play_cur_jrec.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -76,7 +76,7 @@ static void (* const extraction_routine[])() =
uint4 mur_forward_play_cur_jrec(reg_ctl_list *rctl)
{
boolean_t process_losttn;
- boolean_t is_set_kill_zkill_ztrig_ztworm, is_set_kill_zkill_ztrig;
+ boolean_t is_set_kill_zkill_ztworm_lgtrig_ztrig, is_set_kill_zkill_ztrig;
trans_num curr_tn;
enum jnl_record_type rectype;
enum rec_fence_type rec_fence;
@@ -117,8 +117,8 @@ uint4 mur_forward_play_cur_jrec(reg_ctl_list *rctl)
assert(rec_time <= mur_options.before_time);
assert(rec_time >= mur_options.after_time);
assert((0 == mur_options.after_time) || mur_options.forward && !rctl->db_updated);
- is_set_kill_zkill_ztrig_ztworm = (boolean_t)(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype));
- if (is_set_kill_zkill_ztrig_ztworm)
+ is_set_kill_zkill_ztworm_lgtrig_ztrig = (boolean_t)(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype));
+ if (is_set_kill_zkill_ztworm_lgtrig_ztrig)
{
keystr = (jnl_string *)&rec->jrec_set_kill.mumps_node;
# ifdef GTM_CRYPT
@@ -144,7 +144,7 @@ uint4 mur_forward_play_cur_jrec(reg_ctl_list *rctl)
# if (defined(UNIX) && defined(DEBUG))
if ((rec_token_seq < murgbl.losttn_seqno) && murgbl.resync_strm_seqno_nonzero && IS_REPLICATED(rectype))
{
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype) || IS_COM(rectype) || (JRT_NULL == (rectype)));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype) || IS_COM(rectype) || (JRT_NULL == (rectype)));
assert(&rec->jrec_set_kill.strm_seqno == &rec->jrec_null.strm_seqno);
assert(&rec->jrec_set_kill.strm_seqno == &rec->jrec_tcom.strm_seqno);
rec_strm_seqno = GET_STRM_SEQNO(rec);
@@ -224,7 +224,7 @@ uint4 mur_forward_play_cur_jrec(reg_ctl_list *rctl)
* # of participants in the TCOM records across all the participating regions.
*/
assert((NULL == multi) || (BROKEN_TN == recstat) || (FALSE == multi->this_is_broken));
- } else if ((FENCE_ALWAYS == mur_options.fences) && is_set_kill_zkill_ztrig_ztworm)
+ } else if ((FENCE_ALWAYS == mur_options.fences) && is_set_kill_zkill_ztworm_lgtrig_ztrig)
{
process_losttn = rctl->process_losttn = TRUE;
recstat = BROKEN_TN;
@@ -320,7 +320,7 @@ uint4 mur_forward_play_cur_jrec(reg_ctl_list *rctl)
}
if (GOOD_TN == recstat)
{
- if ((is_set_kill_zkill_ztrig_ztworm && !IS_TP(rectype)) || JRT_TCOM == rectype)
+ if ((is_set_kill_zkill_ztworm_lgtrig_ztrig && !IS_TP(rectype)) || JRT_TCOM == rectype)
{
/* Do forward journaling, detecting operations with duplicate transaction numbers.
* While doing journaling on a database, a process may be killed immediately after
diff --git a/sr_port/mur_jnl_ext.c b/sr_port/mur_jnl_ext.c
index d17a6ca..d4b8f03 100644
--- a/sr_port/mur_jnl_ext.c
+++ b/sr_port/mur_jnl_ext.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -54,7 +54,7 @@ error_def(ERR_TEXT);
#define LAB_TERM_SZ (SIZEOF(LAB_TERM) - 1)
/* This routine formats and outputs journal extract records
- corresponding to M SET, KILL, ZKILL, TSTART, ZTSTART, and ZTRIGGER commands as well as $ZTWORMHOLE */
+ corresponding to M SET, KILL, ZKILL, TSTART, ZTSTART, and ZTRIGGER commands, $ZTRIGGER function (LGTRIG) and $ZTWORMHOLE */
void mur_extract_set(jnl_ctl_list *jctl, fi_type *fi, jnl_record *rec, pini_list_struct *plst)
{
enum jnl_record_type rectype;
@@ -104,7 +104,7 @@ void mur_extract_set(jnl_ctl_list *jctl, fi_type *fi, jnl_record *rec, pini_list
EXT_STRM_SEQNO(rec->jrec_set_kill.strm_seqno);
jnlext_write(fi, murgbl.extr_buff, extract_len);
}
- /* Output the SET or KILL or ZKILL or ZTWORMHOLE record */
+ /* Output the SET or KILL or ZKILL or ZTWORMHOLE or LGTRIG or ZTRIG record */
if (!mur_options.detail)
{
extract_len = 0;
@@ -120,6 +120,9 @@ void mur_extract_set(jnl_ctl_list *jctl, fi_type *fi, jnl_record *rec, pini_list
} else if (IS_ZTWORM(rectype))
{
EXT2BYTES(&muext_code[MUEXT_ZTWORM][0]);
+ } else if (IS_LGTRIG(rectype))
+ {
+ EXT2BYTES(&muext_code[MUEXT_LGTRIG][0]);
} else if (IS_ZTRIG(rectype))
{
EXT2BYTES(&muext_code[MUEXT_ZTRIG][0]);
@@ -149,10 +152,12 @@ void mur_extract_set(jnl_ctl_list *jctl, fi_type *fi, jnl_record *rec, pini_list
EXTQW(rec->jrec_set_kill.token_seq.token);
} else
EXTQW(rec->jrec_set_kill.token_seq.jnl_seqno);
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype));
assert(&rec->jrec_set_kill.strm_seqno == &rec->jrec_ztworm.strm_seqno);
+ assert(&rec->jrec_set_kill.strm_seqno == &rec->jrec_lgtrig.strm_seqno);
EXT_STRM_SEQNO(rec->jrec_set_kill.strm_seqno);
assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
+ assert(&rec->jrec_set_kill.update_num == &rec->jrec_lgtrig.update_num);
EXTINT(rec->jrec_set_kill.update_num);
do_format2zwr = FALSE;
if (IS_SET_KILL_ZKILL_ZTRIG(rectype))
@@ -174,8 +179,9 @@ void mur_extract_set(jnl_ctl_list *jctl, fi_type *fi, jnl_record *rec, pini_list
val_ptr += SIZEOF(mstr_len_t);
do_format2zwr = TRUE;
}
- } else if (IS_ZTWORM(rectype))
+ } else if (IS_ZTWORM(rectype) || IS_LGTRIG(rectype))
{
+ assert(&rec->jrec_ztworm.ztworm_str == &rec->jrec_lgtrig.lgtrig_str);
keystr = (jnl_string *)&rec->jrec_ztworm.ztworm_str;
val_len = keystr->length;
val_ptr = &keystr->text[0];
diff --git a/sr_port/mur_open_files.c b/sr_port/mur_open_files.c
index a76ae23..ae1ae32 100644
--- a/sr_port/mur_open_files.c
+++ b/sr_port/mur_open_files.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -52,7 +52,6 @@
#include "mu_rndwn_file.h"
#include "read_db_files_from_gld.h"
#include "mur_db_files_from_jnllist.h"
-#include "gtm_rename.h"
#include "gtmmsg.h"
#include "file_head_read.h"
#include "mupip_exit.h"
@@ -138,23 +137,21 @@
}
#endif
-GBLREF boolean_t blocksig_initialized;
-GBLREF sigset_t block_sigsent;
-GBLREF reg_ctl_list *mur_ctl;
-GBLREF mur_opt_struct mur_options;
-GBLREF mur_gbls_t murgbl;
+GBLREF gd_addr *gd_header;
GBLREF gd_region *gv_cur_region;
GBLREF jnlpool_addrs jnlpool;
-GBLREF gd_addr *gd_header;
+GBLREF mur_opt_struct mur_options;
+GBLREF mur_gbls_t murgbl;
+GBLREF reg_ctl_list *mur_ctl;
GBLREF sgmnt_data *cs_data;
#ifdef UNIX
-GBLREF jnlpool_ctl_ptr_t jnlpool_ctl;
-GBLREF sgmnt_addrs *cs_addrs;
+GBLREF boolean_t jnlpool_init_needed;
GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS];
GBLREF int4 strm_index;
-GBLREF uint4 process_id;
GBLREF jnl_gbls_t jgbl;
-GBLREF boolean_t jnlpool_init_needed;
+GBLREF jnlpool_ctl_ptr_t jnlpool_ctl;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF uint4 process_id;
#endif
@@ -196,12 +193,12 @@ error_def (ERR_ORLBKSTART);
error_def (ERR_REPLSTATEOFF);
error_def (ERR_RLBKNOBIMG);
error_def (ERR_ROLLBKINTERRUPT);
-error_def (ERR_SRVLCKWT2LNG);
error_def (ERR_STARFILE);
error_def (ERR_TEXT);
error_def (ERR_WCBLOCKED);
#define STAR_QUOTE "\"*\""
+
boolean_t mur_open_files()
{
boolean_t interrupted_rollback;
@@ -236,6 +233,7 @@ boolean_t mur_open_files()
sgmnt_data *tmpcsd;
gd_region *reg;
int4 llcnt, max_epoch_interval = 0, idx;
+ int save_errno;
unix_db_info *udi;
now_t now;
char *time_ptr, time_str[CTIME_BEFORE_NL + 2]; /* for GET_CUR_TIME macro */
@@ -307,7 +305,7 @@ boolean_t mur_open_files()
if (!mu_rndwn_repl_instance(&replpool_id, FALSE, TRUE, &jnlpool_sem_created))
return FALSE; /* mu_rndwn_repl_instance will have printed appropriate message in case of error */
assert(jnlpool.jnlpool_ctl == jnlpool_ctl);
- assert(jgbl.onlnrlbk || ANTICIPATORY_FREEZE_AVAILABLE || (NULL == jnlpool_ctl));
+ assert(jgbl.onlnrlbk || INST_FREEZE_ON_ERROR_POLICY || (NULL == jnlpool_ctl));
ASSERT_HOLD_REPLPOOL_SEMS;
assert(NULL != jnlpool.repl_inst_filehdr);
assert(INVALID_SEMID != jnlpool.repl_inst_filehdr->jnlpool_semid);
@@ -334,8 +332,7 @@ boolean_t mur_open_files()
{
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_FILENOTFND, 2, tran_name->len, tran_name->addr);
return FALSE;
- }
- else
+ } else
{
tran_name->len = full_len; /* since on vax, mstr.len is a 'short' */
set_gdid_from_file((gd_id_ptr_t)&file_id, replpool_id.gtmgbldir, tran_name->len);
@@ -380,7 +377,8 @@ boolean_t mur_open_files()
rctl->csd = NULL;
rctl->jctl = rctl->jctl_head = rctl->jctl_alt_head = rctl->jctl_turn_around = rctl->jctl_apply_pblk = NULL;
murgbl.reg_full_total++; /* mur_close_files() expects rctl->csa and rctl->jctl to be initialized.
- * so consider this rctl only after those have been initialized. */
+ * so consider this rctl only after those have been initialized.
+ */
/* Do region specific initialization */
init_hashtab_mname(&rctl->gvntab, 0, HASHTAB_NO_COMPACT, HASHTAB_NO_SPARE_TABLE); /* for mur_forward() */
rctl->db_ctl = (file_control *)malloc(SIZEOF(file_control));
@@ -649,7 +647,6 @@ boolean_t mur_open_files()
{ /* NOTE: Only for collation info extract needs database access */
DEFER_INTERRUPTS(INTRPT_IN_MUR_OPEN_FILES); /* temporarily disable MUPIP STOP/signal handling. */
TP_CHANGE_REG(rctl->gd);
-
csa = rctl->csa = &FILE_INFO(rctl->gd)->s_addrs;
csd = rctl->csd = rctl->csa->hdr;
UNIX_ONLY(assert(!jgbl.onlnrlbk || (csa->now_crit && csa->hold_onto_crit)));
@@ -764,7 +761,8 @@ boolean_t mur_open_files()
}
if (csd->freeze UNIX_ONLY(&& !jgbl.onlnrlbk))
{ /* region_freeze should release freeze here. For ONLINE ROLLBACK we would have
- * waited for the freeze to be lifted off before */
+ * waited for the freeze to be lifted off before
+ */
reg_frz_status = region_freeze(rctl->gd, FALSE, TRUE, FALSE);
assert (0 == rctl->csa->hdr->freeze);
assert(REG_FREEZE_SUCCESS == reg_frz_status);
@@ -802,12 +800,12 @@ boolean_t mur_open_files()
} else
{ /* temporarily disable MUPIP STOP/signal handling. */
DEFER_INTERRUPTS(INTRPT_IN_MUR_OPEN_FILES);
-
/* NOTE: csa field is NULL, if we do not open database */
csd = rctl->csd = (sgmnt_data_ptr_t)malloc(SGMNT_HDR_LEN);
assert(0 == rctl->gd->dyn.addr->fname[rctl->gd->dyn.addr->fname_len]);
/* 1) show 2) extract 3) verify action does not need standalone access.
- * In this case csa is NULL */
+ * In this case csa is NULL
+ */
if (!file_head_read((char *)rctl->gd->dyn.addr->fname, rctl->csd, SGMNT_HDR_LEN))
{
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DBFILOPERR, 2, REG_LEN_STR(rctl->gd));
@@ -820,7 +818,8 @@ boolean_t mur_open_files()
ENABLE_INTERRUPTS(INTRPT_IN_MUR_OPEN_FILES); /* reenable the interrupts */
}
/* For star_specified we open journal files here.
- * For star_specified we cannot do anything if journaling is disabled */
+ * For star_specified we cannot do anything if journaling is disabled
+ */
if (star_specified && JNL_ALLOWED(csd))
{
jctl = (jnl_ctl_list *)malloc(SIZEOF(jnl_ctl_list));
@@ -830,8 +829,10 @@ boolean_t mur_open_files()
memcpy(jctl->jnl_fn, csd->jnl_file_name, csd->jnl_file_len);
jctl->jnl_fn[jctl->jnl_fn_len] = 0;
/* If system crashed during rename, following will fix it .
- * Following function is directly related to cre_jnl_file_common */
- cre_jnl_file_intrpt_rename(jctl->jnl_fn_len, jctl->jnl_fn);
+ * Following function is directly related to cre_jnl_file_common
+ */
+ if (rctl->standalone || (rctl->csa && rctl->csa->now_crit))
+ cre_jnl_file_intrpt_rename(rctl->csa);
if (!mur_fopen(jctl))
{
return FALSE;
@@ -896,7 +897,8 @@ boolean_t mur_open_files()
/* At this point mur_ctl[] has been created from the current global directory database file names
* or from the journal file header's database names.
* For star_specified == TRUE implicitly only current generation journal files are specified and already opened
- * For star_specified == FALSE user can specify multiple generations. We need to sort them */
+ * For star_specified == FALSE user can specify multiple generations. We need to sort them
+ */
if (!star_specified)
{
jnlno = 0;
@@ -917,7 +919,6 @@ boolean_t mur_open_files()
return FALSE;
}
cptr++; /* skip separator */
- /* Note cre_jnl_file_intrpt_rename was already called in mur_db_files_from_jnllist */
if (!mur_fopen(jctl)) /* dont know rctl yet */
{
return FALSE;
@@ -956,8 +957,8 @@ boolean_t mur_open_files()
{
VMS_ONLY(set_gdid_from_file(&jctl->fid, (char *)jctl->jnl_fn, jctl->jnl_fn_len);)
# if defined(UNIX)
- if (filename_to_id(&jctl->fid, (char *)jctl->jnl_fn))
- {
+ if (SS_NORMAL == (save_errno = filename_to_id(&jctl->fid, (char *)jctl->jnl_fn)))
+ { /* WARNING: assignment above */
# endif
for (temp_jctl = rctl->jctl_head; temp_jctl; temp_jctl = temp_jctl->next_gen)
{
@@ -971,11 +972,10 @@ boolean_t mur_open_files()
}
}
# if defined(UNIX)
- }
- else
+ } else
{
gtm_putmsg_csa(CSA_ARG(JCTL2CSA(jctl)) VARLSTCNT(11) ERR_JNLFILEOPNERR, 2, jctl->jnl_fn_len,
- jctl->jnl_fn, ERR_SYSCALL, 5, LEN_AND_LIT("fstat"), CALLFROM, errno);
+ jctl->jnl_fn, ERR_SYSCALL, 5, LEN_AND_LIT("fstat"), CALLFROM, save_errno);
return FALSE;
}
# endif
@@ -1034,9 +1034,9 @@ boolean_t mur_open_files()
} /* mur_options.forward */
} /* for jnlno */
}
-
/* If not all regions of a global directory are processed, we shrink mur_ctl array and conserve space.
- * It is specially needed for later code */
+ * It is specially needed for later code
+ */
murgbl.reg_total = murgbl.reg_full_total;
for (regno = 0; regno < murgbl.reg_total; regno++)
{
@@ -1066,7 +1066,8 @@ boolean_t mur_open_files()
if (0 == murgbl.reg_total)
return FALSE;
/* From this point consider only regions with journals to be processed (murgbl.reg_total)
- * However mur_close_files will close all regions opened (murgbl.reg_full_total) */
+ * However mur_close_files will close all regions opened (murgbl.reg_full_total)
+ */
for (rctl = mur_ctl, rctl_top = mur_ctl + murgbl.reg_total; rctl < rctl_top; rctl++)
{
jctl = rctl->jctl_head;
diff --git a/sr_port/mur_output_record.c b/sr_port/mur_output_record.c
index 181d12b..4a3b322 100644
--- a/sr_port/mur_output_record.c
+++ b/sr_port/mur_output_record.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -43,6 +43,9 @@
#ifdef GTM_TRIGGER
#include <rtnhdr.h>
#include "gv_trigger.h"
+#include "gdskill.h"
+#include "tp.h"
+#include "t_begin.h"
#endif
/* Include prototypes */
#include "t_qread.h"
@@ -56,20 +59,21 @@
#include "gtmcrypt.h"
#endif
-GBLREF mur_opt_struct mur_options;
-GBLREF jnl_gbls_t jgbl;
-GBLREF gv_namehead *gv_target;
-GBLREF gd_region *gv_cur_region;
-GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF uint4 dollar_tlevel;
GBLREF boolean_t write_after_image;
+GBLREF gd_region *gv_cur_region;
+GBLREF gv_namehead *gv_target;
GBLREF jnl_fence_control jnl_fence_ctl; /* Needed to set the token, optimize jnl_write_logical for recover */
-GBLREF struct_jrec_tcom tcom_record;
+GBLREF jnl_gbls_t jgbl;
GBLREF jnl_process_vector *prc_vec;
GBLREF mur_gbls_t murgbl;
+GBLREF mur_opt_struct mur_options;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF struct_jrec_tcom tcom_record;
+GBLREF uint4 dollar_tlevel;
error_def(ERR_JNLBADRECFMT);
+error_def(ERR_TRIGLOADFAIL);
/* This routine is called only for recover and rollback (that is, mur_options.update).
* It applies the set/kill/zkill, tcom, inctn, and aimg records during forward processing.
@@ -259,19 +263,37 @@ uint4 mur_output_record(reg_ctl_list *rctl)
# ifdef GTM_TRIGGER
case JRT_TZTWORM:
case JRT_UZTWORM:
+ case JRT_TLGTRIG:
+ case JRT_ULGTRIG:
+ assert(JRT_TLGTRIG > JRT_UZTWORM);
+ assert(JRT_TLGTRIG > JRT_TZTWORM);
+ assert(JRT_TLGTRIG < JRT_ULGTRIG);
+ if (JRT_TLGTRIG <= rectype)
+ {
+ assert(dollar_tlevel);
+ /* Below is needed to set update_trans TRUE on this region even if NO db updates happen to ^#t nodes.
+ * Only then is the db curr_tn incremented as part of the tcommit and the tn numbers played by forward
+ * phase of recovery (backward or forward recovery) will match the tn numbers in later journal records.
+ */
+ T_BEGIN_SETORKILL_NONTP_OR_TP(ERR_TRIGLOADFAIL);
+ }
if (jnl_enabled)
- { /* Format the ZTWORM journal record */
+ { /* Format the ZTWORM or LGTRIG journal record (both have same jnl record layout) */
assert(dollar_tlevel); /* op_tstart should already have been done by mur_forward */
+ assert(rec->jrec_ztworm.token_seq.token == rec->jrec_lgtrig.token_seq.token);
MUR_SET_JNL_FENCE_CTL_TOKEN(rec->jrec_ztworm.token_seq.token, rctl);
+ assert(rec->jrec_ztworm.strm_seqno == rec->jrec_lgtrig.strm_seqno);
jnl_fence_ctl.strm_seqno = rec->jrec_ztworm.strm_seqno;
+ assert(rec->jrec_ztworm.update_num == rec->jrec_lgtrig.update_num);
jgbl.tp_ztp_jnl_upd_num = rec->jrec_ztworm.update_num;
DEBUG_ONLY(jgbl.max_tp_ztp_jnl_upd_num = MAX(jgbl.max_tp_ztp_jnl_upd_num, jgbl.tp_ztp_jnl_upd_num);)
jgbl.mur_jrec_nodeflags = 0;
+ assert(&rec->jrec_ztworm.ztworm_str == &rec->jrec_lgtrig.lgtrig_str);
keystr = (jnl_string *)&rec->jrec_ztworm.ztworm_str;
mv.str.addr = &keystr->text[0];
mv.str.len = keystr->length;
mv.mvtype = MV_STR;
- ztworm_jfb = jnl_format(JNL_ZTWORM, NULL, &mv, 0);
+ ztworm_jfb = jnl_format((JRT_TLGTRIG > rectype) ? JNL_ZTWORM : JNL_LGTRIG, NULL, &mv, 0);
assert(NULL != ztworm_jfb);
}
break;
diff --git a/sr_port/mur_put_aimg_rec.c b/sr_port/mur_put_aimg_rec.c
index 0cd2607..82b8890 100644
--- a/sr_port/mur_put_aimg_rec.c
+++ b/sr_port/mur_put_aimg_rec.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -39,27 +39,29 @@
#include "t_end.h"
#include "gvcst_blk_build.h"
#include "t_begin_crit.h"
+#include "gtmmsg.h"
-GBLREF gd_region *gv_cur_region;
GBLREF char *update_array, *update_array_ptr;
-GBLREF uint4 update_array_size; /* for the BLK_* macros */
-GBLREF srch_hist dummy_hist;
-GBLREF sgmnt_addrs *cs_addrs;
-GBLREF sgmnt_data_ptr_t cs_data;
GBLREF cw_set_element cw_set[];
-GBLREF jnl_format_buffer *non_tp_jfb_ptr;
+GBLREF gd_region *gv_cur_region;
/* Modified on the similar lines of dse AIMG record logic, needed for recover to write journal records */
+GBLREF jnl_format_buffer *non_tp_jfb_ptr;
+GBLREF sgmnt_addrs *cs_addrs;
+GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF srch_hist dummy_hist;
+GBLREF uint4 update_array_size; /* for the BLK_* macros */
+
+error_def(ERR_AIMGBLKFAIL);
+error_def(ERR_MURAIMGFAIL);
void mur_put_aimg_rec(jnl_record *rec)
{
- sm_uc_ptr_t aimg_blk_ptr;
- int4 blk_seg_cnt, blk_size;
blk_segment *bs1, *bs_ptr;
cw_set_element *cse;
+ int4 blk_seg_cnt, blk_size;
+ sm_uc_ptr_t aimg_blk_ptr;
srch_blk_status blkhist;
- error_def(ERR_MURAIMGFAIL);
-
/* Applying an after image record should use t_begin/t_end mechanisms instead of just copying over
* the aimg block into the t_qread buffer. This is because there are lots of other things like
* making the cache-record become dirty in case of BG and some others to do in case of MM.
@@ -67,19 +69,17 @@ void mur_put_aimg_rec(jnl_record *rec)
*/
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
assert(!cs_addrs->now_crit || cs_addrs->hold_onto_crit);
-
t_begin_crit(ERR_MURAIMGFAIL);
assert(cs_addrs->now_crit);
blk_size = cs_addrs->hdr->blk_size;
blkhist.blk_num = rec->jrec_aimg.blknum;
- if (NULL == (blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
- GTMASSERT;
+ assertpro (NULL != (blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)));
aimg_blk_ptr = (sm_uc_ptr_t)&rec->jrec_aimg.blk_contents[0];
BLK_INIT(bs_ptr, bs1);
BLK_SEG(bs_ptr, (uchar_ptr_t)aimg_blk_ptr + SIZEOF(blk_hdr), (int)((blk_hdr_ptr_t)aimg_blk_ptr)->bsiz - SIZEOF(blk_hdr));
if (!BLK_FINI(bs_ptr, bs1))
{
- util_out_print("Error: bad blk build.", TRUE);
+ gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_AIMGBLKFAIL, 3, rec->jrec_aimg.blknum, DB_LEN_STR(gv_cur_region));
t_abort(gv_cur_region, cs_addrs);
return;
}
diff --git a/sr_port/mur_read_file.c b/sr_port/mur_read_file.c
index 0bcd56d..590acef 100644
--- a/sr_port/mur_read_file.c
+++ b/sr_port/mur_read_file.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -717,8 +717,7 @@ uint4 mur_fread_eof_crash(jnl_ctl_list *jctl, off_jnl_t lo_off, off_jnl_t hi_off
mur_read_desc_t *mur_desc;
assert(JNL_HDR_LEN <= jctl->jfh->alignsize);
- if (lo_off < jctl->jfh->end_of_data || lo_off > hi_off)
- GTMASSERT;
+ assertpro((lo_off >= jctl->jfh->end_of_data) && (lo_off <= hi_off));
jctl->properly_closed = FALSE;
if (SS_NORMAL != (status = mur_valrec_prev(jctl, lo_off, hi_off)))
return status;
@@ -824,18 +823,16 @@ uint4 mur_valrec_prev(jnl_ctl_list *jctl, off_jnl_t lo_off, off_jnl_t hi_off)
break;
mid_off = new_mid_off + mid_further;
}
- if (0 == jctl->rec_offset)
- { /* Unexpected condition:
- * a) If lo_off was 0 while entering this routine, this means there was no good record at or after the beginning
- * of the journal file (i.e. offset of JNL_HDR_LEN). This is impossible since a PINI record was written at
- * journal file creation time and at least that should have been seen as a good record.
- * b) If lo_off was non-zero while entering this routine, this implies there was no good record anywhere at or
- * after an offset of lo_off in the journal file. But this is impossible since a non-zero value of lo_off
- * implies it is equal to jfh->end_of_data which means that an EPOCH/EOF record written at that offset
- * and the journal file was synced so we should at least see that good record.
- */
- GTMASSERT;
- }
+ /* Unexpected condition:
+ * a) If lo_off was 0 while entering this routine, this means there was no good record at or after the beginning
+ * of the journal file (i.e. offset of JNL_HDR_LEN). This is impossible since a PINI record was written at
+ * journal file creation time and at least that should have been seen as a good record.
+ * b) If lo_off was non-zero while entering this routine, this implies there was no good record anywhere at or
+ * after an offset of lo_off in the journal file. But this is impossible since a non-zero value of lo_off
+ * implies it is equal to jfh->end_of_data which means that an EPOCH/EOF record written at that offset
+ * and the journal file was synced so we should at least see that good record.
+ */
+ assertpro(0 != jctl->rec_offset);
/* We found a valid record at mid_off, go forward to find the last valid record. Before the for loop
* of mur_next(0) following call is necessary to initialize buffers and for the assumptions in mur_next() */
rec_offset = jctl->rec_offset;
@@ -872,14 +869,12 @@ uint4 mur_valrec_prev(jnl_ctl_list *jctl, off_jnl_t lo_off, off_jnl_t hi_off)
jctl->rec_offset = rec_offset;
/* now set mur_desc fields to point to valid record */
assert(rec_offset);
- if (SS_NORMAL != mur_prev(jctl, rec_offset))
- { /* Since valid record may have been overwritten we must do this.
- * We call mur_prev, not mur_next, although both position mur_desc to the same
- * record (when called with non zero arg) to make sure no assumptions in
- * successive calls to mur_prev(jctl, 0) are violated.
- */
- GTMASSERT;
- }
+ /* Since valid record may have been overwritten we must do this.
+ * We call mur_prev, not mur_next, although both position mur_desc to the same
+ * record (when called with non zero arg) to make sure no assumptions in
+ * successive calls to mur_prev(jctl, 0) are violated.
+ */
+ assertpro(SS_NORMAL == mur_prev(jctl, rec_offset));
return SS_NORMAL;
}
@@ -909,8 +904,7 @@ uint4 mur_valrec_next(jnl_ctl_list *jctl, off_jnl_t lo_off)
break;
if (ERR_JNLBADRECFMT != status)
return status; /* I/O error or unexpected failure */
- if (jctl->rec_offset >= jctl->lvrec_off) /* lvrec_off must have a valid record */
- GTMASSERT;
+ assertpro(jctl->rec_offset < jctl->lvrec_off); /* lvrec_off must have a valid record */
}
assert(SS_NORMAL == status);
/* now work backwards to find the earliest valid record in the immediately preceding alignsize chunk */
@@ -1067,7 +1061,7 @@ boolean_t mur_fopen(jnl_ctl_list *jctl)
{
INIT_PROC_ENCRYPTION(cs_addrs, gtmcrypt_errno);
if (0 == gtmcrypt_errno)
- GTMCRYPT_GETKEY(cs_addrs, jfh->encryption_hash, jctl->encr_key_handle, gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(cs_addrs, jfh->encryption_hash, jctl->encr_key_handle, gtmcrypt_errno);
if (0 != gtmcrypt_errno)
GTMCRYPT_REPORT_ERROR(MAKE_MSG_WARNING(gtmcrypt_errno), gtm_putmsg, jctl->jnl_fn_len, jctl->jnl_fn);
if (NULL != mur_ctl->csd && (0 != memcmp(mur_ctl->csd->encryption_hash, jfh->encryption_hash, GTMCRYPT_HASH_LEN)))
diff --git a/sr_port/mur_validate_checksum.c b/sr_port/mur_validate_checksum.c
index 1b8a5d0..465db6b 100644
--- a/sr_port/mur_validate_checksum.c
+++ b/sr_port/mur_validate_checksum.c
@@ -1,6 +1,6 @@
/****************************************************************
*
- * Copyright 2005, 2012 Fidelity Information Services, Inc *
+ * Copyright 2005, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -43,10 +43,11 @@ boolean_t mur_validate_checksum(jnl_ctl_list *jctl)
mur_desc = rctl->mur_desc;
jnlrec = mur_desc->jnlrec;
rectype = (enum jnl_record_type)jnlrec->prefix.jrec_type;
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype)) /* TUPD/UUPD/FUPD/GUPD */
+ if (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype)) /* TUPD/UUPD/FUPD/GUPD */
{
COMPUTE_COMMON_CHECKSUM(tmp_csum, jnlrec->prefix);
assert(&jnlrec->jrec_set_kill.mumps_node == &jnlrec->jrec_ztworm.ztworm_str);
+ assert(&jnlrec->jrec_set_kill.mumps_node == &jnlrec->jrec_lgtrig.lgtrig_str);
start_ptr = (unsigned char *)&jnlrec->jrec_set_kill.mumps_node;
end_ptr = (unsigned char *)(jnlrec) + mur_desc->jreclen - JREC_SUFFIX_SIZE;
rec_csum = jnl_get_checksum((uint4 *)start_ptr, NULL, (int)(end_ptr - start_ptr));
diff --git a/sr_port/mval2fao.c b/sr_port/mval2fao.c
index d0bf183..4a81af0 100644
--- a/sr_port/mval2fao.c
+++ b/sr_port/mval2fao.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -10,16 +10,9 @@
****************************************************************/
/*
- *-----------------------------------------------------------------------------
- This routine takes an arbitrary list of mvals and converts it to an
- array of fao parameters, for use in a subsequent output call.
-
- The parameters list is determined by the fao control string, message,
- with limitations on the number of parameters allowed, and the
- buffer space available for certain fao directive formats.
-
- The caller should call va_end.
- *-----------------------------------------------------------------------------
+ * This routine takes an arbitrary list of mvals and converts it to an array of fao parameters, for use in a subsequent output
+ * call. The parameters list is determined by the fao control string, message, with limitations on the number of parameters allowed,
+ * and the buffer space available for certain fao directive formats. The caller should call va_end.
*/
#include "mdef.h"
@@ -32,98 +25,136 @@
#include "mval2fao.h"
int mval2fao(
- char *message, /* text of message in fao format */
- va_list pfao, /* argument list of caller */
- UINTPTR_T *outparm, /* array of resulting fao parameters */
- int mcount, int fcount, /* mvalcount and faocount */
- char *bufbase, char *buftop) /* buffer space for !AC and !AS */
+ char *message, /* Text of message in fao format. */
+ va_list pfao, /* Argument list of caller. */
+ UINTPTR_T *outparm, /* Array of resulting fao parameters. */
+ int mcount, int fcount, /* mvalcount and faocount. */
+ char *bufbase, char *buftop) /* Buffer space for strings and indirect arguments. */
{
char *buf;
- int i, parmcnt, num;
+ int n, parmcnt, indir_index;
+ gtm_int64_t num;
mval *fao;
fao = va_arg(pfao, mval *);
parmcnt = 0;
+ /* Storage of indirect arguments is at the end of the array. */
+ indir_index = NUM_OF_FAO_SLOTS;
buf = bufbase;
- for ( ; mcount && parmcnt < fcount; )
+ for ( ; mcount && (parmcnt < fcount); )
{
MV_FORCE_DEFINED(fao);
while (*message != '!')
message++;
- for (i=0;(*++message > 47) && (*message < 58);i++) /* a length for the fao parameter */
+ /* A length for the fao parameter (consisting of digits). */
+ for (n = 0; (*++message > 47) && (*message < 58); n++)
;
switch (*message++)
{
case '/':
case '_':
case '^':
- case '!': break;
- case 'A': MV_FORCE_STR(fao);
- switch(*message++)
- {
-/* ascii counted string */ case 'C':
- if ((fao)->str.len > 256 || (fao)->str.len < 0)
- return -1;
- if (buf + (fao)->str.len + 1 >= buftop)
- return -1;
- *buf++ = (fao)->str.len;
- memcpy(buf, (fao)->str.addr, (fao)->str.len);
- buf += (fao)->str.len;
- break;
-/* len,addr string, '.' filled */ case 'F':
-/* len,addr string */ case 'D':
- if (parmcnt + 2 > fcount)
- return parmcnt;
- outparm[parmcnt++] = (unsigned int)(fao)->str.len;
- outparm[parmcnt++] = (UINTPTR_T)(fao)->str.addr;
- break;
-/* ascii string descriptor */ case 'S':
- if (buf + SIZEOF(desc_struct) >= buftop)
- return -1;
- ((desc_struct *)buf)->len = (fao)->str.len;
- ((desc_struct *)buf)->addr = (fao)->str.addr;
- outparm[parmcnt++] = (UINTPTR_T)buf;
- buf += SIZEOF(desc_struct);
- break;
- default: return -1;
- }
- fao = va_arg(pfao, mval *);
- mcount--;
- break;
-/* octal number */ case 'O':
-/* hex number */ case 'X':
-/* signed number */ case 'S':
- num = MV_FORCE_INT(fao);
- switch(*message++)
- {
- case 'B': outparm[parmcnt++] = (UINTPTR_T)num;
- break;
- case 'W': outparm[parmcnt++] = (UINTPTR_T)num;
- break;
- case 'L': outparm[parmcnt++] = (UINTPTR_T)num;
- break;
- default: return -1;
- }
- fao = va_arg(pfao, mval *);
- mcount--;
- break;
-/* zero filled num */ case 'Z':
-/* unsigned num */ case 'U':
- num = MV_FORCE_INT(fao);
- switch(*message++)
- {
- case 'B': outparm[parmcnt++] = (UINTPTR_T)num;
- break;
- case 'W': outparm[parmcnt++] = (UINTPTR_T)num;
- break;
- case 'L': outparm[parmcnt++] = (UINTPTR_T)num;
+ case '!':
+ break;
+/* String */ case 'A':
+ MV_FORCE_STR(fao);
+ switch (*message++)
+ {
+/* ASCII counted string */ case 'C':
+ /* Since the maximum length that could be encoded in one byte is 255, the total
+ * length of the mval can be at most 256 (the byte containing the count plus 255
+ * bytes of the actual string.
+ */
+ if (((fao)->str.len > 256) || ((fao)->str.len < 0))
+ return -1;
+ if (buf + (fao)->str.len + 1 >= buftop)
+ return -1;
+ outparm[parmcnt++] = (UINTPTR_T)buf;
+ *buf++ = (fao)->str.len;
+ memcpy(buf, (fao)->str.addr, (fao)->str.len);
+ buf += (fao)->str.len;
+ break;
+/* len,addr string, '.' filled */ case 'F':
+/* len,addr string */ case 'D':
+ if (parmcnt + 2 > fcount)
+ return parmcnt;
+ outparm[parmcnt++] = (unsigned int)(fao)->str.len;
+ outparm[parmcnt++] = (UINTPTR_T)(fao)->str.addr;
+ break;
+/* ASCII string descriptor */ case 'S':
+ if (buf + SIZEOF(desc_struct) >= buftop)
+ return -1;
+ ((desc_struct *)buf)->len = (fao)->str.len;
+ ((desc_struct *)buf)->addr = (fao)->str.addr;
+ outparm[parmcnt++] = (UINTPTR_T)buf;
+ buf += SIZEOF(desc_struct);
+ break;
+/* NULL-terminated string */ case 'Z':
+ if (buf + (fao)->str.len + 1 >= buftop)
+ return -1;
+ outparm[parmcnt++] = (UINTPTR_T)buf;
+ memcpy(buf, (fao)->str.addr, (fao)->str.len);
+ buf += (fao)->str.len;
+ *buf++ = '\0';
+ break;
+ default:
+ return -1;
+ }
+ fao = va_arg(pfao, mval *);
+ mcount--;
+ break;
+/* Octal number */ case 'O':
+/* Hex number */ case 'X':
+/* Signed number */ case 'S':
+/* Zero-filled num */ case 'Z':
+/* Unsigned num */ case 'U':
+ /* Extracting the value as an integer, since util_format will take care of further casting. */
+ num = mval2i8(fao);
+ switch (*message++)
+ {
+ case 'B':
+ case 'W':
+ case 'L':
+ case 'J':
+ outparm[parmcnt++] = (UINTPTR_T)num;
+ break;
+ default:
+ return -1;
+ }
+ fao = va_arg(pfao, mval *);
+ mcount--;
+ break;
+/* Indirect argument */ case '@':
+ switch (*message++)
+ {
+/* Zero-filled num */ case 'Z':
+/* Unsigned num */ case 'U':
+ case 'X':
+ num = mval2i8(fao);
+ switch (*message++)
+ {
+ case 'J':
+ case 'Q':
+ indir_index -= GTM64_ONLY(1) NON_GTM64_ONLY(2);
+ *(gtm_int64_t *)(outparm + indir_index) = num;
+ outparm[parmcnt++] = (UINTPTR_T)(&outparm[indir_index]);
break;
- default: return -1;
- }
- fao = va_arg(pfao, mval *);
- mcount--;
- break;
- default: return -1;
+ default:
+ return -1;
+ }
+ fao = va_arg(pfao, mval *);
+ mcount -= 1;
+ /* Either we already processed all the arguments, or we should still have room in
+ * our array for another indirect argument.
+ */
+ assert((0 == mcount) || (parmcnt + GTM64_ONLY(1) NON_GTM64_ONLY(2) < indir_index));
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
}
}
return parmcnt;
diff --git a/sr_port/nil_iocontrol.c b/sr_port/nil_iocontrol.c
index 5fa9a10..9f9f2a8 100644
--- a/sr_port/nil_iocontrol.c
+++ b/sr_port/nil_iocontrol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,7 +12,7 @@
#include "mdef.h"
#include "io.h"
-void nil_iocontrol(mstr *d)
+void nil_iocontrol(mstr *mn, int4 argcnt, va_list args)
{
/**** SHOULD BE 'NOT SUPPORTED FOR THIS DEVICE TYPE ****/
return;
diff --git a/sr_port/objlabel.h b/sr_port/objlabel.h
index 032d736..18e0a25 100644
--- a/sr_port/objlabel.h
+++ b/sr_port/objlabel.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,7 +33,7 @@
* Note that OBJ_UNIX_LABEL and OBJ_PLATFORM_LABEL should not exceed 255.
*/
-#define OBJ_UNIX_LABEL 27 /* When changed, be sure to zero the platform specific numbers below (if any non-0) */
+#define OBJ_UNIX_LABEL 28 /* When changed, be sure to zero the platform specific numbers below (if any non-0) */
#if defined(__osf__)
# define OBJ_PLATFORM_LABEL 0 /* Alpha/Tru64 */
diff --git a/sr_port/op.h b/sr_port/op.h
index e8eba3b..aad8bed 100644
--- a/sr_port/op.h
+++ b/sr_port/op.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -102,11 +102,9 @@ void op_fnzbitor(mval *dst, mval *bitstr1, mval *bitstr2);
void op_fnzbitset(mval *dst, mval *bitstr, int pos, int truthval);
void op_fnzbitstr(mval *bitstr, int size, int truthval);
void op_fnzbitxor(mval *dst, mval *bitstr1, mval *bitstr2);
-#ifdef __sun
-void op_fnzcall(unsigned int n_mvals, ...);
-#elif defined(VMS)
+#ifdef VMS
void op_fnzcall(mval *dst, ...);
-#elif defined(UNIX)
+#else
void op_fnzcall(void); /* stub only */
#endif
void op_fnzchar(UNIX_ONLY_COMMA(int cnt) mval *dst, ...);
@@ -136,13 +134,15 @@ void op_fnzpopulation(mval *arg1, mval *arg2, mval *dst);
void op_fnzpriv(mval *prv, mval *ret);
void op_fnzqgblmod(mval *v);
void op_fnzreverse(mval *src, mval *dst);
-int op_fnzsearch(mval *file, mint indx, mval *ret); /***type int added***/
+int op_fnzsearch(mval *file, mint indx, mint mfunc, mval *ret); /***type int added***/
void op_fnzsetprv(mval *prv, mval *ret);
void op_fnzsigproc(int processid, int signum, mval *retcode);
+void op_fnzsocket(UNIX_ONLY_COMMA(int numarg) mval *dst, ...);
void op_fnzsqlexpr(mval *value, mval *target);
void op_fnzsqlfield(int findex, mval *target);
#ifdef UNIX
void op_fnzsubstr(mval *src, int start, int bytelen, mval *dest);
+void op_fnzsyslog(mval *src, mval *dst);
#endif
void op_fnztranslate(mval *src, mval *in_str , mval *out_str, mval *dst);
void op_fnztrigger(mval *func, mval *arg1, mval *arg2, mval *dst);
@@ -298,6 +298,7 @@ void op_zdeallocate(int4 timeout);
void op_zedit(mval *v, mval *p);
void op_zg1(int4 level);
void op_zgoto(mval *rtnname, mval *lblname, int offset, int level);
+void op_zrupdate(int argcnt, ...);
# ifdef UNIX
/* note op_ztrigger.c is present even in non-GTM_TRIGGER UNIX environments but is not runnable */
void op_ztrigger(void);
diff --git a/sr_port/op_bindparm.c b/sr_port/op_bindparm.c
index 501f4a3..df8ea72 100644
--- a/sr_port/op_bindparm.c
+++ b/sr_port/op_bindparm.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -15,6 +15,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include "lv_val.h"
#include <rtnhdr.h>
#include "mv_stent.h"
@@ -114,6 +115,7 @@ void op_bindparm(UNIX_ONLY_COMMA(int frmc) int frmp_arg, ...)
{ /* Actual list parm - dotted pass-by-reference parm */
PUSH_MV_STENT(MVST_NTAB);
ntab = &mv_chain->mv_st_cont.mvs_ntab;
+ ntab->hte_addr = NULL; /* In case table gets expanded before we set it below */
new_var = *actp;
/* This sort of parameter is considered an alias */
assert(0 < new_var->stats.trefcnt);
diff --git a/sr_port/op_clralsvars.c b/sr_port/op_clralsvars.c
index a7b2f4a..f1ee790 100644
--- a/sr_port/op_clralsvars.c
+++ b/sr_port/op_clralsvars.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_string.h"
#include "gtm_stdio.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
diff --git a/sr_port/op_exfunret.c b/sr_port/op_exfunret.c
index c04d04a..d450580 100644
--- a/sr_port/op_exfunret.c
+++ b/sr_port/op_exfunret.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2012 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,6 +11,9 @@
#include "mdef.h"
+#include "gtm_stdio.h"
+
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
@@ -48,13 +51,18 @@ void op_exfunret(mval *retval)
savtyp = retval->mvtype;
retval->mvtype &= ~MV_RETARG;
if (0 == (MV_RETARG & savtyp))
- /* if dollar_zquit_anyway is TRUE, then do not give an error when no value is returned from an
+ { /* if dollar_zquit_anyway is TRUE, then do not give an error when no value is returned from an
* extrinsic; just make the return value NULL instead
*/
if (dollar_zquit_anyway)
*retval = literal_null;
else
- rts_error(VARLSTCNT(1) ERR_QUITARGREQD);
+ {
+ assert(0 == (MV_ALIASCONT & savtyp));
+ assert(NULL == alias_retarg);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_QUITARGREQD);
+ }
+ }
if (0 != (MV_ALIASCONT & savtyp))
{ /* We have an alias container return which has already had its reference counts increased. Remove
* the extra reference counts before we raise the actual error since the assignment and thus the
@@ -65,9 +73,9 @@ void op_exfunret(mval *retval)
assert(srclvc->stats.trefcnt >= srclvc->stats.crefcnt);
assert(1 <= srclvc->stats.crefcnt); /* Verify is existing container ref */
DECR_CREFCNT(srclvc);
- DECR_TREFCNT(srclvc);
+ DECR_BASE_REF_NOSYM(srclvc, FALSE);
alias_retarg = NULL;
- rts_error(VARLSTCNT(1) ERR_QUITALSINV);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_QUITALSINV);
}
assert(NULL == alias_retarg);
}
diff --git a/sr_port/op_exp.c b/sr_port/op_exp.c
index eb4dbfa..3ab2c46 100644
--- a/sr_port/op_exp.c
+++ b/sr_port/op_exp.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -104,14 +104,14 @@ void op_exp(mval *u, mval* v, mval *p)
{ /* Base is integer-ish */
if (0 > u1_p->m[1])
{ /* Base is negative, invalid exponent expression */
- rts_error(VARLSTCNT(1) ERR_NEGFRACPWR);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NEGFRACPWR);
return;
}
} else
{ /* Base is NOT integer-sh */
if (u1_p->sgn)
{ /* Base is negative, invalid exponent expression */
- rts_error(VARLSTCNT(1) ERR_NEGFRACPWR);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NEGFRACPWR);
return;
}
}
@@ -197,7 +197,7 @@ void op_exp(mval *u, mval* v, mval *p)
}
if (fraction && neg)
{ /* Fractional exponent and negative base not valid */
- rts_error(VARLSTCNT(1) ERR_NEGFRACPWR);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NEGFRACPWR);
return;
}
}
@@ -207,12 +207,11 @@ void op_exp(mval *u, mval* v, mval *p)
# ifdef UNIX
if (HUGE_VAL == z) /* Infinity return value check */
{
- rts_error(VARLSTCNT(1) ERR_NUMOFLOW);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NUMOFLOW);
return;
}
# endif
- assert(!neg); /* Should be taken care of in one of the op_mul() using sections dealing with whole exponents */
- p->sgn = 0; /* Positive numbers only from here on out */
+ p->sgn = (neg && !even); /* Positive numbers only from here on out */
if (0 == z)
{
*p = literal_zero;
@@ -242,7 +241,7 @@ void op_exp(mval *u, mval* v, mval *p)
z2 = (double)n1 / MV_BIAS;
if (fabs(z - z2) < accuracy)
{ /* We can treat this as a GT.M int */
- ((mval_b *)p)->sgne = 0;
+ p->e = 0;
p->mvtype = (MV_NM | MV_INT);
p->m[0] = 0;
p->m[1] = (p->sgn) ? -n1 : n1;
@@ -283,7 +282,7 @@ void op_exp(mval *u, mval* v, mval *p)
* check. Not expecting it to ever be invoked but is here as a safety net.
*/
z1_rnd /= ten_pwr[-3-n];
- ((mval_b *)p)->sgne = 0;
+ p->e = 0;
p->mvtype = (MV_NM | MV_INT);
p->m[1] = z1_rnd;
return;
@@ -291,7 +290,7 @@ void op_exp(mval *u, mval* v, mval *p)
exponent = MV_XBIAS + n + 9;
if (exponent >= EXPHI)
{
- rts_error(VARLSTCNT(1) ERR_NUMOFLOW);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NUMOFLOW);
return;
}
if (exponent < EXPLO)
diff --git a/sr_port/op_fnname.c b/sr_port/op_fnname.c
index 47aeae0..bb0429f 100644
--- a/sr_port/op_fnname.c
+++ b/sr_port/op_fnname.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -100,7 +100,7 @@ void op_fnname(UNIX_ONLY_COMMA(int sub_count) mval *finaldst, ...)
int depth_count, fnname_type;
mval *dst, *arg, *depth;
VMS_ONLY(int sub_count;)
- mstr format_out;
+ mstr format_out, opstr;
va_list var;
unsigned char *sptr, *key_ptr, *key_top;
@@ -114,7 +114,7 @@ void op_fnname(UNIX_ONLY_COMMA(int sub_count) mval *finaldst, ...)
if (depth_count < 0)
{
va_end(var);
- rts_error(VARLSTCNT(1) ERR_FNNAMENEG);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_FNNAMENEG);
}
/* Note about garbage collection : *dst and all possible *arg's in this function are anchored in the stringpool chains
* and preserved during garbage collection (run time argument mvals provided by compiler). So, if we maintain dst->str.len
@@ -136,7 +136,7 @@ void op_fnname(UNIX_ONLY_COMMA(int sub_count) mval *finaldst, ...)
if (!gv_currkey || gv_currkey->prev == 0)
{
va_end(var);
- rts_error(VARLSTCNT(1) ERR_GVNAKED);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GVNAKED);
}
/* Reserve enough space for naked reference. Include space for ^() and a maximum of sub_count ',' separators for
* subscripts specified as arguments to $NAME() in addition to those in the naked reference
@@ -157,7 +157,9 @@ void op_fnname(UNIX_ONLY_COMMA(int sub_count) mval *finaldst, ...)
{
for ( ; ; )
{
- sptr = gvsub2str(key_ptr, sptr, TRUE); /* gvsub2str assumes enough buffer available */
+ opstr.addr = (char *)sptr;
+ opstr.len = space_needed;
+ sptr = gvsub2str(key_ptr, &opstr, TRUE); /* gvsub2str assumes enough buffer available */
while (*key_ptr++)
;
if (depth_count != MAXPOSINT4) /* although this may not make a difference in reality, */
@@ -244,7 +246,7 @@ void op_fnname(UNIX_ONLY_COMMA(int sub_count) mval *finaldst, ...)
}
va_end(var);
if (MAX_STRLEN < dst->str.len)
- rts_error(VARLSTCNT(1) ERR_MAXSTRLEN);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_MAXSTRLEN);
*finaldst = *dst;
POP_MV_STENT(); /* don't need no temporary no more */
return;
diff --git a/sr_port/op_fntext.c b/sr_port/op_fntext.c
index b59caa4..4874294 100644
--- a/sr_port/op_fntext.c
+++ b/sr_port/op_fntext.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -25,10 +25,10 @@
#endif
#include "stack_frame.h"
-GBLREF spdesc stringpool;
-GBLREF stack_frame *frame_pointer;
+GBLREF spdesc stringpool;
+GBLREF stack_frame *frame_pointer;
+GBLREF uint4 dollar_tlevel;
-error_def(ERR_TXTSRCMAT);
error_def(ERR_ZLINKFILE);
error_def(ERR_ZLMODULE);
@@ -66,12 +66,12 @@ void op_fntext(mval *label, int int_exp, mval *rtn, mval *ret)
if (is_trigger)
{
DBGTRIGR((stderr, "op_fntext: fetching $TEXT() source for a trigger\n"));
- assert(FALSE == TREF(in_op_fntext));
- TREF(in_op_fntext) = TRUE;
+ assert(0 == TREF(op_fntext_tlevel));
+ TREF(op_fntext_tlevel) = 1 + dollar_tlevel;
}
#endif
stat = get_src_line(temp_rtn, label, int_exp, &sld, VERIFY);
- GTMTRIG_ONLY(TREF(in_op_fntext) = FALSE);
+ GTMTRIG_ONLY(TREF(op_fntext_tlevel) = 0);
}
if (0 == (stat & (CHECKSUMFAIL | NEGATIVELINE)))
{
diff --git a/sr_port/op_fnview.c b/sr_port/op_fnview.c
index 588c801..16d4c4a 100644
--- a/sr_port/op_fnview.c
+++ b/sr_port/op_fnview.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -72,6 +72,7 @@ GBLREF int gv_fillfactor;
GBLREF int4 gtm_max_sockets;
GBLREF gv_key *gv_currkey;
GBLREF boolean_t is_gtm_chset_utf8;
+UNIX_ONLY(GBLREF boolean_t dmterm_default;)
error_def(ERR_COLLATIONUNDEF);
error_def(ERR_GBLNOMAPTOREG);
@@ -85,6 +86,14 @@ LITREF mval literal_zero;
LITREF mval literal_one;
LITREF mval literal_null;
+#define MM_RES "MM"
+#define BG_RES "BG"
+#define CM_RES "CM"
+#define USR_RES "USR"
+#define GTM_BOOL_RES "GT.M Boolean short-circuit"
+#define STD_BOOL_RES "Standard Boolean evaluation side effects"
+#define WRN_BOOL_RES "Standard Boolean with side-effect warning"
+
STATICFNDCL unsigned char *gvn2gds(mval *gvn, gv_key *gvkey, int act);
#define COPY_ARG_TO_STRINGPOOL(DST, KEYEND, KEYSTART) \
@@ -202,20 +211,20 @@ void op_fnview(UNIX_ONLY_COMMA(int numarg) mval *dst, ...)
switch (REG_ACC_METH(parmblk.gv_ptr))
{
case dba_mm:
- tmpstr.addr = "MM";
- tmpstr.len = SIZEOF("MM")-1;
+ tmpstr.addr = MM_RES;
+ tmpstr.len = SIZEOF(MM_RES)-1;
break;
case dba_bg:
- tmpstr.addr = "BG";
- tmpstr.len = SIZEOF("BG")-1;
+ tmpstr.addr = BG_RES;
+ tmpstr.len = SIZEOF(BG_RES)-1;
break;
case dba_cm:
- tmpstr.addr = "CM";
- tmpstr.len = SIZEOF("CM")-1;
+ tmpstr.addr = CM_RES;
+ tmpstr.len = SIZEOF(CM_RES)-1;
break;
case dba_usr:
- tmpstr.addr = "USR";
- tmpstr.len = SIZEOF("USR")-1;
+ tmpstr.addr = USR_RES;
+ tmpstr.len = SIZEOF(USR_RES)-1;
break;
default:
assertpro(FALSE && REG_ACC_METH(parmblk.gv_ptr));
@@ -226,16 +235,16 @@ void op_fnview(UNIX_ONLY_COMMA(int numarg) mval *dst, ...)
switch (TREF(gtm_fullbool))
{
case GTM_BOOL:
- tmpstr.addr = "GT.M Boolean short-circuit";
- tmpstr.len = SIZEOF("GT.M Boolean short-circuit")-1;
+ tmpstr.addr = GTM_BOOL_RES;
+ tmpstr.len = SIZEOF(GTM_BOOL_RES)-1;
break;
case FULL_BOOL:
- tmpstr.addr = "Standard Boolean evaluation side effects";
- tmpstr.len = SIZEOF("Standard Boolean evaluation side effects")-1;
+ tmpstr.addr = STD_BOOL_RES;
+ tmpstr.len = SIZEOF(STD_BOOL_RES)-1;
break;
case FULL_BOOL_WARN:
- tmpstr.addr = "Boolean side-effect warning";
- tmpstr.len = SIZEOF("Boolean side-effect warning")-1;
+ tmpstr.addr = WRN_BOOL_RES;
+ tmpstr.len = SIZEOF(WRN_BOOL_RES)-1;
break;
default:
assertpro(FALSE && TREF(gtm_fullbool));
@@ -691,6 +700,9 @@ void op_fnview(UNIX_ONLY_COMMA(int numarg) mval *dst, ...)
dst->str = relink_allowed_mstr[TREF(relink_allowed)];
s2pool(&dst->str);
break;
+ case VTK_DMTERM:
+ n = dmterm_default;
+ break;
# endif
default:
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_VIEWFN);
@@ -855,7 +867,7 @@ STATICFNDEF unsigned char *gvn2gds(mval *gvn, gv_key *gvkey, int act)
break; /* bad function name. issue error after breaking from for loop */
}
for (c2 = (unsigned char *)&fnname[0]; c1 < c; c2++, c1++)
- *c2 = toupper(*c1);
+ *c2 = TOUPPER(*c1);
if (!MEMCMP_LIT(fnname, "ZCHAR") || !MEMCMP_LIT(fnname, "ZCH"))
is_zchar = 1;
else if (!MEMCMP_LIT(fnname, "CHAR") || !MEMCMP_LIT(fnname, "C"))
diff --git a/sr_port/dse_is_blk_free.h b/sr_port/op_fnzsearch.h
similarity index 52%
rename from sr_port/dse_is_blk_free.h
rename to sr_port/op_fnzsearch.h
index 23b7777..4e14e02 100644
--- a/sr_port/dse_is_blk_free.h
+++ b/sr_port/op_fnzsearch.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,12 +9,14 @@
* *
****************************************************************/
-#ifndef DSE_IS_BLK_FREE_DEFINED
+#ifndef FNZSEARCH_H_INCLUDED
+#define FNZSEARCH_H_INCLUDED
-/* Declare parms for dse_is_blk_free.c */
+/* Define stream limits and special stream values used internally */
-bool dse_is_blk_free (block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr);
+#define MAX_STRM_CT 256
-#define DSE_IS_BLK_FREE_DEFINED
+#define STRM_ZRUPDATE -1 /* Stream used by ZRUPDATE command when processing wildcards */
+#define STRM_COMP_SRC -2 /* Stream used by compile_source_file() */
#endif
diff --git a/sr_port/op_fnzsocket.c b/sr_port/op_fnzsocket.c
new file mode 100644
index 0000000..dd922e4
--- /dev/null
+++ b/sr_port/op_fnzsocket.c
@@ -0,0 +1,400 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include <stdarg.h>
+#include "gtm_string.h"
+
+#include "stringpool.h"
+#include "error.h"
+#include "nametabtyp.h"
+#include "namelook.h"
+#include "io.h"
+#include "iosp.h"
+#include "gtm_netdb.h"
+#include "gtm_socket.h"
+#include "gtm_un.h"
+#include "gtm_inet.h"
+#include "gtm_ipv6.h"
+#include "iosocketdef.h"
+#include "op.h"
+#include "mvalconv.h"
+#include "trans_log_name.h"
+#include "zsocket.h"
+
+GBLREF spdesc stringpool;
+GBLREF io_pair io_curr_device;
+GBLREF io_log_name *io_root_log_name;
+GBLREF d_socket_struct *socket_pool;
+
+error_def(ERR_ZSOCKETATTR);
+error_def(ERR_ZSOCKETNOTSOCK);
+error_def(ERR_IONOTOPEN);
+
+LITREF mval literal_zero;
+LITREF mval literal_one;
+LITREF mval literal_null;
+LITREF mval skiparg;
+
+#define ZSOCKETITEM(A,B,C,D) {(SIZEOF(A) - 1), A}
+const nametabent zsocket_names[] =
+{
+#include "zsockettab.h" /* BYPASSOK */
+};
+#undef ZSOCKETITEM
+const unsigned char zsocket_indextab[] =
+{ /* A B C D E F G H I J K L M N */
+ 0, 0, 0, 1, 3, 3, 3, 3, 4, 6, 6, 6, 8, 9,
+ /* O P Q R S T U V W X Y Z end */
+ 10, 10, 12, 12, 14, 16, 16, 16, 16, 16, 16, 16, 20
+};
+#define ZSOCKETITEM(A,B,C,D) C
+static const int zsocket_types[] =
+{
+#include "zsockettab.h" /* BYPASSOK */
+};
+#undef ZSOCKETITEM
+#define ZSOCKETITEM(A,B,C,D) D
+static const int zsocket_level[] =
+{
+#include "zsockettab.h"
+};
+#undef ZSOCKETITEM
+LITDEF mval literal_local = DEFINE_MVAL_LITERAL(MV_STR | MV_NUM_APPROX, 0, 0, (SIZEOF("LOCAL") - 1), "LOCAL", 0, 0);
+LITDEF mval literal_tcp = DEFINE_MVAL_LITERAL(MV_STR | MV_NUM_APPROX, 0, 0, (SIZEOF("TCP") - 1), "TCP", 0, 0);
+LITDEF mval literal_tcp6 = DEFINE_MVAL_LITERAL(MV_STR | MV_NUM_APPROX, 0, 0, (SIZEOF("TCP6") - 1), "TCP6", 0, 0);
+LITDEF char *zsocket_state_names[] = {"CONNECTED", "LISTENING", "BOUND", "CREATED", "CONNECTINPROGRESS"};
+LITDEF char *zsocket_howcreated_names[] = {"LISTEN", "ACCEPTED", "CONNECT", "PRINCIPAL", "PASSED"};
+
+#define GET_SOCKETPTR_INDEX(DSOCK, INDEX, SOCKETPTR) \
+{ \
+ INDEX = (NULL != arg1) ? (!M_ARG_SKIPPED(arg1) ? mval2i(arg1) : DSOCK->current_socket) : (DSOCK->n_socket + 1); \
+ if ((0 < DSOCK->n_socket) && (INDEX <= DSOCK->n_socket)) \
+ SOCKETPTR = DSOCK->socket[INDEX]; \
+ else \
+ SOCKETPTR = NULL; \
+}
+
+void op_fnzsocket(UNIX_ONLY_COMMA(int numarg) mval *dst, ...)
+{
+ VMS_ONLY(int numarg;)
+ int zsocket_item, zsocket_type, tmpnum, numret, index, index2;
+ int4 stat;
+ mval *arg1, *arg2, tmpmval;
+ mval *keyword;
+ mval *devicename;
+ mstr tn; /* translated name */
+ io_desc *iod;
+ io_log_name *nl, *tl;
+ char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */
+ d_socket_struct *dsocketptr;
+ socket_struct *socketptr;
+ va_list var;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ VMS_ONLY(va_count(numarg));
+ assertpro(2 <= numarg);
+ VAR_START(var, dst);
+ assertpro(NULL != dst);
+ devicename = va_arg(var, mval *);
+ if ((NULL != devicename) && !M_ARG_SKIPPED(devicename))
+ MV_FORCE_STR(devicename);
+ else
+ devicename = NULL; /* use stringpool */
+ keyword = va_arg(var, mval *);
+ MV_FORCE_STR(keyword);
+ numarg -= 3; /* remove destination, device, and keyword from count */
+ if (numarg > 0)
+ {
+ arg1 = va_arg(var, mval *);
+ if (--numarg > 0)
+ {
+ arg2 = va_arg(var, mval *);
+ DEBUG_ONLY(--numarg;)
+ } else
+ arg2 = (mval *)NULL;
+ } else
+ {
+ arg1 = (mval *)NULL;
+ arg2 = (mval *)NULL;
+ }
+ assert(!numarg);
+ va_end(var);
+ if (NULL == devicename)
+ {
+ if ((NULL == socket_pool) || (NULL == socket_pool->iod))
+ {
+ *dst = literal_null; /* no socketpool device yet */
+ return;
+ }
+ iod = socket_pool->iod;
+ }
+ else if (0 == devicename->str.len)
+ iod = io_curr_device.in;
+ else
+ { /* get information from provided device name */
+ nl = get_log_name(&devicename->str, NO_INSERT);
+ if (NULL == nl)
+ {
+ stat = TRANS_LOG_NAME(&devicename->str, &tn, buf1, SIZEOF(buf1), dont_sendmsg_on_log2long);
+ if (SS_NORMAL != stat)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_IONOTOPEN);
+ else
+ {
+ if (0 == (tl = get_log_name(&tn, NO_INSERT)))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_IONOTOPEN);
+ nl = tl;
+ }
+ }
+ if (!nl->iod || (dev_open != nl->iod->state))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_IONOTOPEN);
+ iod = nl->iod;
+ }
+ if (gtmsocket != iod->type)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZSOCKETNOTSOCK);
+ }
+ dsocketptr = (d_socket_struct *)iod->dev_sp;
+ if ((zsocket_item = namelook(zsocket_indextab, zsocket_names, keyword->str.addr, keyword->str.len)) < 0)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZSOCKETATTR, 2, keyword->str.len, keyword->str.addr);
+ }
+ zsocket_type = zsocket_types[zsocket_item];
+ if ((level_socket == zsocket_level[zsocket_item]) && (zsocket_index != zsocket_item))
+ {
+ GET_SOCKETPTR_INDEX(dsocketptr, index, socketptr);
+ if (NULL == socketptr)
+ { /* index out of bounds */
+ *dst = literal_null;
+ return;
+ }
+ }
+ switch (zsocket_item)
+ {
+ case zsocket_currindex:
+ numret = (int)dsocketptr->current_socket;
+ break;
+ case zsocket_delimiter:
+ if (NULL == arg2)
+ { /* want how many delimiters */
+ numret = socketptr->n_delimiter;
+ zsocket_type = MV_NM;
+ } else
+ {
+ index2 = mval2i(arg2);
+ if ((0 > index2) || (index2 > socketptr->n_delimiter - 1))
+ { /* not in range */
+ *dst = literal_null;
+ zsocket_type = MV_STR;
+ } else
+ { /* return UTF-8 or M */
+ dst->str = socketptr->delimiter[index2];
+ s2pool(&dst->str);
+ zsocket_type = MV_STR;
+ }
+ }
+ break;
+ case zsocket_descriptor:
+ numret = socketptr->sd;
+ break;
+ case zsocket_howcreated:
+ assert(creator_passed >= socketptr->howcreated);
+ dst->str.addr = (char *)zsocket_howcreated_names[socketptr->howcreated];
+ dst->str.len = STRLEN(dst->str.addr);
+ UNICODE_ONLY(dst->str.char_len = 0);
+ s2pool(&dst->str);
+ break;
+ case zsocket_index:
+ if (M_ARG_SKIPPED(arg1))
+ {
+ numret = (int)dsocketptr->current_socket;
+ if (0 > numret)
+ {
+ *dst = literal_null;
+ zsocket_type = MV_STR;
+ }
+ } else if ((NULL == arg1) || (0 == arg1->str.len))
+ {
+ *dst = literal_null;
+ zsocket_type = MV_STR;
+ } else
+ {
+ MV_FORCE_STR(arg1);
+ numret = iosocket_handle(arg1->str.addr, &arg1->str.len, FALSE, dsocketptr);
+ if (0 > numret)
+ {
+ *dst = literal_null;
+ zsocket_type = MV_STR;
+ }
+ }
+ break;
+ case zsocket_ioerror:
+ if (socketptr->ioerror)
+ *dst = literal_one;
+ else
+ *dst = literal_zero;
+ break;
+ case zsocket_localaddress:
+ if (NULL != socketptr->local.saddr_ip)
+ {
+ dst->str.addr = socketptr->local.saddr_ip;
+ dst->str.len = STRLEN(socketptr->local.saddr_ip);
+# ifndef VMS
+ } else if (socket_local == socketptr->protocol)
+ {
+ if (NULL != socketptr->local.sa)
+ dst->str.addr = ((struct sockaddr_un *)(socketptr->local.sa))->sun_path;
+ else if (NULL != socketptr->remote.sa) /* CONNECT */
+ dst->str.addr = ((struct sockaddr_un *)(socketptr->remote.sa))->sun_path;
+ else
+ {
+ *dst = literal_null;
+ break;
+ }
+ dst->str.len = STRLEN(dst->str.addr);
+# endif
+ } else
+ *dst = literal_null;
+ UNICODE_ONLY(dst->str.char_len = 0);
+ s2pool(&dst->str);
+ break;
+ case zsocket_localport:
+ if ((NULL != socketptr->local.sa) || socketptr->passive)
+ numret = (int)socketptr->local.port;
+ else
+ {
+ *dst = literal_null;
+ zsocket_type = MV_STR;
+ }
+ break;
+ case zsocket_morereadtime:
+ if (socketptr->def_moreread_timeout) /* user specified */
+ numret = (int)socketptr->moreread_timeout;
+ else
+ {
+ *dst = literal_null;
+ zsocket_type = MV_STR;
+ }
+ break;
+ case zsocket_number:
+ numret = (int)dsocketptr->n_socket;
+ break;
+ case zsocket_parent:
+ if (NULL != socketptr->parenthandle)
+ {
+ dst->str.addr = socketptr->parenthandle;
+ dst->str.len = STRLEN(socketptr->parenthandle);
+ UNICODE_ONLY(dst->str.char_len = 0);
+ s2pool(&dst->str);
+ } else
+ *dst = literal_null;
+ break;
+ case zsocket_protocol:
+# ifndef VMS
+ if (socket_local == socketptr->protocol)
+ *dst = literal_local;
+ else
+# endif
+ {
+ if (NULL != socketptr->remote.sa)
+ tmpnum= socketptr->remote.ai.ai_family;
+ else if (NULL != socketptr->local.sa)
+ tmpnum= socketptr->local.ai.ai_family;
+ else
+ tmpnum = AF_UNSPEC;
+ switch (tmpnum)
+ {
+ case AF_INET:
+ *dst = literal_tcp;
+ break;
+ case AF_INET6:
+ *dst = literal_tcp6;
+ break;
+ default:
+ *dst = literal_null;
+ }
+ }
+ break;
+ case zsocket_remoteaddress:
+ if (NULL != socketptr->remote.saddr_ip)
+ {
+ dst->str.addr = socketptr->remote.saddr_ip;
+ dst->str.len = STRLEN(socketptr->remote.saddr_ip);
+# ifndef VMS
+ } else if (socket_local == socketptr->protocol)
+ {
+ if (NULL != socketptr->remote.sa)
+ dst->str.addr = ((struct sockaddr_un *)(socketptr->remote.sa))->sun_path;
+ else if (NULL != socketptr->remote.sa) /* CONNECT */
+ dst->str.addr = ((struct sockaddr_un *)(socketptr->local.sa))->sun_path;
+ else
+ {
+ *dst = literal_null;
+ break;
+ }
+ dst->str.len = STRLEN(dst->str.addr);
+# endif
+ } else
+ *dst = literal_null;
+ UNICODE_ONLY(dst->str.char_len = 0);
+ s2pool(&dst->str);
+ break;
+ case zsocket_remoteport:
+ if (NULL != socketptr->remote.sa)
+ numret = (int)socketptr->remote.port;
+ else
+ {
+ *dst = literal_null;
+ zsocket_type = MV_STR;
+ }
+ break;
+ case zsocket_sockethandle:
+ dst->str.addr = socketptr->handle;
+ dst->str.len = socketptr->handle_len;
+ UNICODE_ONLY(dst->str.char_len = 0);
+ s2pool(&dst->str);
+ break;
+ case zsocket_state:
+ assert(socket_connect_inprogress >= socketptr->state);
+ dst->str.addr = (char *)zsocket_state_names[socketptr->state];
+ dst->str.len = STRLEN(dst->str.addr);
+ UNICODE_ONLY(dst->str.char_len = 0);
+ s2pool(&dst->str);
+ break;
+ case zsocket_zbfsize:
+ numret = socketptr->buffer_size;
+ break;
+ case zsocket_zdelay:
+ if (socketptr->nodelay)
+ *dst = literal_zero;
+ else
+ *dst = literal_one;
+ break;
+ case zsocket_zff:
+ if (0 < socketptr->zff.len)
+ {
+ dst->str = socketptr->zff;
+ s2pool(&dst->str);
+ } else
+ *dst = literal_null;
+ break;
+ case zsocket_zibfsize:
+ numret = socketptr->bufsiz;
+ break;
+ default:
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZSOCKETATTR, 2, keyword->str.len, keyword->str.addr);
+ }
+ dst->mvtype = zsocket_type;
+ if (MV_NM == dst->mvtype)
+ MV_FORCE_MVAL(dst, numret);
+}
diff --git a/sr_port/op_gvnext.c b/sr_port/op_gvnext.c
index ab1cdfd..d2c9ec9 100644
--- a/sr_port/op_gvnext.c
+++ b/sr_port/op_gvnext.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,6 +40,7 @@ void op_gvnext(mval *v)
int4 n;
register char *c;
gvnh_reg_t *gvnh_reg;
+ mstr opstr;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -107,7 +108,9 @@ void op_gvnext(mval *v)
}
v->str.addr = (char *)stringpool.free;
c = (char *)(&gv_altkey->base[0] + gv_altkey->prev);
- stringpool.free = gvsub2str ((uchar_ptr_t)c,stringpool.free, FALSE);
+ opstr.addr = v->str.addr;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ stringpool.free = gvsub2str((uchar_ptr_t)c, &opstr, FALSE);
v->str.len = INTCAST(stringpool.free - (unsigned char *) v->str.addr);
assert (v->str.addr < (char *) stringpool.top && v->str.addr >= (char *) stringpool.base);
assert (v->str.addr + v->str.len <= (char *) stringpool.top
diff --git a/sr_port/op_gvorder.c b/sr_port/op_gvorder.c
index b22051a..417ec45 100644
--- a/sr_port/op_gvorder.c
+++ b/sr_port/op_gvorder.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -53,6 +53,7 @@ void op_gvorder(mval *v)
gv_namehead *gvt;
gvnh_reg_t *gvnh_reg;
gvnh_spanreg_t *gvspan;
+ mstr opstr;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -106,7 +107,9 @@ void op_gvorder(mval *v)
ENSURE_STP_FREE_SPACE(n);
}
v->str.addr = (char *)stringpool.free;
- stringpool.free = gvsub2str (&gv_altkey->base[0] + gv_altkey->prev, stringpool.free, FALSE);
+ opstr.addr = v->str.addr;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ stringpool.free = gvsub2str(&gv_altkey->base[0] + gv_altkey->prev, &opstr, FALSE);
v->str.len = INTCAST((char *)stringpool.free - v->str.addr);
assert(v->str.addr < (char *)stringpool.top && v->str.addr >= (char *)stringpool.base);
assert(v->str.addr + v->str.len <= (char *)stringpool.top &&
diff --git a/sr_port/op_halt.c b/sr_port/op_halt.c
index d8124b8..7d502f6 100644
--- a/sr_port/op_halt.c
+++ b/sr_port/op_halt.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -38,12 +38,12 @@ void op_halt(void)
/* If HALT is done from a non-runtime trigger, send a warning message to oplog to record the fact
* of this uncommon process termination method.
*/
- if (!IS_GTM_IMAGE && !IS_GTM_SVC_DAL_IMAGE)
+ if (!IS_GTM_IMAGE)
{
zposition.mvtype = 0; /* It's not an mval yet till getzposition fills it in */
getzposition(&zposition);
assert(MV_IS_STRING(&zposition) && (0 < zposition.str.len));
- send_msg(VARLSTCNT(9) ERR_PROCTERM, 7, GTMIMAGENAMETXT(image_type), RTS_ERROR_TEXT("HALT"),
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_PROCTERM, 7, GTMIMAGENAMETXT(image_type), RTS_ERROR_TEXT("HALT"),
0, zposition.str.len, zposition.str.addr);
}
# endif
diff --git a/sr_port/op_iocontrol.c b/sr_port/op_iocontrol.c
index 7859f39..6bd3dd3 100644
--- a/sr_port/op_iocontrol.c
+++ b/sr_port/op_iocontrol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,7 @@
#include "mdef.h"
#include "gtm_string.h"
+#include "gtm_strings.h"
#include "stringpool.h"
#include "io.h"
@@ -28,90 +29,29 @@
GBLREF spdesc stringpool;
GBLREF io_pair io_curr_device;
+LITDEF MSTR_CONST(literal_accept, "ACCEPT");
+LITDEF MSTR_CONST(literal_listen, "LISTEN");
+LITDEF MSTR_CONST(literal_wait, "WAIT");
+
+#define MSTR_CASE_EQ(x, y) (((x)->len == (y)->len) && !STRNCASECMP((x)->addr, (y)->addr, (x)->len))
+
error_def(ERR_CTLMNEMAXLEN);
void op_iocontrol(UNIX_ONLY_COMMA(int4 n) mval *vparg, ...)
{
va_list var;
- mval *vp;
VMS_ONLY(int n;)
- int count, m;
- unsigned char *cp, *cq, *cpmax;
- boolean_t overflow;
- int length;
- mstr val;
VAR_START(var, vparg);
VMS_ONLY(va_count(n);)
assert(0 < n);
MV_FORCE_STR(vparg);
- for (count = 1; count < n; count++)
- {
- vp = va_arg(var, mval *);
- MV_FORCE_STR(vp);
- }
+ if (MSTR_CASE_EQ(&vparg->str, &literal_accept)
+ || MSTR_CASE_EQ(&vparg->str, &literal_listen)
+ || MSTR_CASE_EQ(&vparg->str, &literal_wait))
+ (*io_curr_device.in->disp_ptr->iocontrol)(&vparg->str, n-1, var);
+ else
+ (*io_curr_device.out->disp_ptr->iocontrol)(&vparg->str, n-1, var);
va_end(var);
- /* Format of generated argument is:
- * if n=1 KEYWORD
- * if n>1 KEYWORD(PAR1,PAR2,...PARx)
- */
- VAR_START(var, vparg);
- vp = vparg;
- ENSURE_STP_FREE_SPACE(MAX_DEVCTL_LENGTH + 1); /* Plus 1 to allow for null terminator char sockets need */
- /* Note in this calculation, cpmax is the true maximum value for cp so cp can be equal to but not greater than cpmax */
- cpmax = stringpool.free + MAX_DEVCTL_LENGTH;
- overflow = FALSE;
- for (cp = stringpool.free, count = 0 ; count < n; count++)
- {
- if (0 < count)
- {
- vp = va_arg(var, mval *);
- *cp++ = (1 == count) ? '(' : ',';
- LIMITCHECK(cp, cpmax);
- }
- if (MV_IS_CANONICAL(vp))
- {
- m = (int)vp->str.len;
- LIMITCHECK((cp + m), cpmax); /* Check before move for multiple chars */
- memcpy(cp, vp->str.addr, m);
- cp += m;
- } else
- {
- if (0 < count)
- {
- *cp++ = '"';
- LIMITCHECK(cp, cpmax);
- }
- for (m = 0, cq = (unsigned char *)vp->str.addr, length = (int)vp->str.len; m < length; m++)
- {
- if ('"' == *cq)
- {
- *cp++ = '"';
- LIMITCHECK(cp, cpmax);
- }
- *cp++ = *cq++;
- LIMITCHECK(cp, cpmax);
- }
- if (0 < count)
- {
- *cp++ = '"';
- LIMITCHECK(cp, cpmax);
- }
- }
- }
- va_end(var);
- if ((1 < count) && !overflow)
- {
- *cp++ = ')';
- if (cp > cpmax)
- overflow = TRUE;
- }
- if (overflow)
- rts_error(VARLSTCNT(1) ERR_CTLMNEMAXLEN);
- assert(cp <= cpmax);
- val.len = INTCAST(cp - stringpool.free);
- assert(val.len <= MAX_DEVCTL_LENGTH);
- val.addr = (char *)stringpool.free;
- (*io_curr_device.out->disp_ptr->iocontrol)(&val);
return;
}
diff --git a/sr_port/op_killalias.c b/sr_port/op_killalias.c
index 2b3fc99..e9d65b5 100644
--- a/sr_port/op_killalias.c
+++ b/sr_port/op_killalias.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
@@ -28,13 +29,10 @@
GBLREF stack_frame *frame_pointer;
GBLREF symval *curr_symval;
GBLREF uint4 dollar_tlevel;
-GBLREF lv_val *active_lv;
/* Operation - Kill an alias (unsubscripted variable)
*
- * Look it up in the hash table and remove the pointer to the lv_val to destroy the
- * alias association. Will need to do this in any previous symtabs this var is in
- * as well.
+ * Look it up in the hash table and remove the pointer to the lv_val to destroy the alias association.
*/
void op_killalias(int srcindx)
{
@@ -43,9 +41,8 @@ void op_killalias(int srcindx)
lv_val *lv;
int4 symvlvl;
- active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful. clear active_lv to avoid later
- * cleanup problems.
- */
+ SET_ACTIVE_LV(NULL, TRUE, actlv_op_killalias); /* If we get here, subscript set was successful.
+ * Clear active_lv to avoid later cleanup issues */
varname = &(((mname_entry *)frame_pointer->vartab_ptr)[srcindx]);
tabent = lookup_hashtab_mname(&curr_symval->h_symtab, varname); /* Retrieve hash tab entry this var */
if (tabent)
diff --git a/sr_port/op_killaliasall.c b/sr_port/op_killaliasall.c
index 4f8abc1..f772b71 100644
--- a/sr_port/op_killaliasall.c
+++ b/sr_port/op_killaliasall.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "op.h"
#include "gdsroot.h"
@@ -24,12 +25,11 @@
#include "gdsbt.h"
#include "gdsfhead.h"
#include "alias.h"
+#include <rtnhdr.h>
+#include "stack_frame.h"
GBLREF symval *curr_symval;
-GBLREF lv_val *active_lv;
GBLREF uint4 dollar_tlevel;
-GBLREF mstr **stp_array;
-GBLREF int stp_array_size;
/* Delete all aliases and the data they point to.
*
@@ -50,19 +50,15 @@ GBLREF int stp_array_size;
*/
void op_killaliasall(void)
{
- ht_ent_mname *tabent, *tabent_top, **htearray, **htearraytop, **htep;
+ ht_ent_mname *tabent, *tabent_top;
lv_val *lvp, *lvp_top, *lvrefp;
symval *symv;
int lowest_symvlvl;
+ ht_ent_mname **htearraycur = NULL, **htearray = NULL, **htearraytop;
- active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful. clear active_lv to avoid later
- * cleanup problems */
+ SET_ACTIVE_LV(NULL, TRUE, actlv_op_killaliasall); /* If we get here, subscript set was successful.
+ * Clear active_lv to avoid later cleanup issues */
lowest_symvlvl = MAXPOSINT4;
- if (NULL == stp_array)
- /* Same initialization as is in stp_gcol_src.h */
- stp_array = (mstr **)malloc((stp_array_size = STP_MAXITEMS) * SIZEOF(mstr *));
- htearray = htep = (ht_ent_mname **)stp_array;
- htearraytop = htearray + stp_array_size;
/* First pass through hash table we record HTEs that have > 1 trefcnt. We will delete these in a later
* loop but don't want to delete any until all are found.
@@ -72,13 +68,7 @@ void op_killaliasall(void)
if (HTENT_VALID_MNAME(tabent, lv_val, lvp) && lvp && (1 < lvp->stats.trefcnt))
{ /* Verify room in the table, expand if necessary */
assert(LV_IS_BASE_VAR(lvp));
- if (htep >= htearraytop)
- { /* No room and the inn .. expand */
- stp_expand_array();
- htearray = htep = (ht_ent_mname **)stp_array;
- htearraytop = htearray + stp_array_size;
- }
- *htep++ = tabent;
+ ADD_TO_STPARRAY(tabent, htearray, htearraycur, htearraytop, ht_ent_mname);
/* Need to find the lowest level symval that is affected by this kill * so we can mark all necessary
* symvals as having had alias activity.
*/
@@ -99,15 +89,14 @@ void op_killaliasall(void)
* that likewise need to be processed (and de-container-ized).
*/
assert(LV_IS_BASE_VAR(lvp));
- if (LV_HAS_CHILD(lvp))
- KILL_CNTNRS_IN_TREE(lvp);
+ KILL_CNTNRS_IN_TREE(lvp); /* Note macro has LV_GET_CHILD() check in it */
}
}
/* Now we can go through the hash table entries we identified in the first step and delete them. */
- for (htearraytop = htep, htep = htearray; htep < htearraytop; ++htep)
+ for (htearraytop = htearraycur, htearraycur = htearray; htearraycur < htearraytop; ++htearraycur)
{
- assert(htep);
- tabent = *htep;
+ assert(htearraycur);
+ tabent = *htearraycur;
lvp = (lv_val *)tabent->value;
assert(lvp);
assert(LV_IS_BASE_VAR(lvp));
diff --git a/sr_port/op_merge.c b/sr_port/op_merge.c
index a0cf9f2..845dcf1 100644
--- a/sr_port/op_merge.c
+++ b/sr_port/op_merge.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -30,6 +30,9 @@
*/
#include "mdef.h"
+#include "gtm_stdio.h"
+
+#include "gtmio.h"
#include "min_max.h"
#include "lv_val.h"
#include <rtnhdr.h>
@@ -66,16 +69,6 @@
#include "alias.h"
#include "gtmimagename.h"
-#define UNDO_ACTIVE_LV \
-{ \
- if (NULL != active_lv) \
- { \
- if (!LV_IS_VAL_DEFINED(active_lv) && !LV_HAS_CHILD(active_lv)) \
- op_kill(active_lv); \
- active_lv = (lv_val *)NULL; \
- } \
-}
-
GBLREF sgmnt_addrs *cs_addrs;
GBLREF mv_stent *mv_chain;
GBLREF unsigned char *msp, *stackwarn, *stacktop;
@@ -88,7 +81,9 @@ GBLREF int merge_args;
GBLREF merge_glvn_ptr mglvnp;
GBLREF gv_namehead *gv_target;
GBLREF lvzwrite_datablk *lvzwrite_block;
+#ifdef DEBUG
GBLREF lv_val *active_lv;
+#endif
error_def(ERR_MAXNRSUBSCRIPTS);
error_def(ERR_MERGEINCOMPL);
@@ -114,6 +109,10 @@ void op_merge(void)
gv_namehead *gvt1, *gvt2;
gvnh_reg_t *gvnh_reg1, *gvnh_reg2;
gvname_info *gblp1, *gblp2;
+ mstr opstr;
+# ifdef DEBUG
+ lv_val *orig_active_lv;
+# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -129,6 +128,7 @@ void op_merge(void)
value->mvtype = 0; /* initialize mval in the M-stack in case stp_gcol gets called before value gets initialized below */
gblp1 = mglvnp->gblp[IND1];
gblp2 = mglvnp->gblp[IND2];
+ DEBUG_ONLY(orig_active_lv = active_lv;)
if (MARG2_IS_GBL(merge_args))
{ /* Need to protect mkey returned from gvcst_queryget from stpgcol */
PUSH_MV_STENT(MVST_MVAL);
@@ -138,10 +138,11 @@ void op_merge(void)
gbl2_gd_addr = TREF(gd_targ_addr);
/* now $DATA will be done for gvn2. op_gvdata input parameters are set in the form of some GBLREF */
op_gvdata(value);
- dollardata_src = MV_FORCE_INT(value);
+ dollardata_src = MV_FORCE_INTD(value);
if (0 == dollardata_src)
{ /* nothing in source global */
- UNDO_ACTIVE_LV;
+ assert(orig_active_lv == active_lv);
+ UNDO_ACTIVE_LV(actlv_op_merge1); /* kill "dst" and parents as applicable if $data(dst)=0 */
POP_MV_STENT(); /* value */
POP_MV_STENT(); /* mkey */
if (MARG1_IS_GBL(merge_args))
@@ -284,7 +285,9 @@ void op_merge(void)
{
assert(gv_target == gvt1);
gv_target = gvt2; /* switch gv_target for "mval2subsc" */
- ptr2 = gvsub2str(ptr, buff, FALSE);
+ opstr.addr = (char *)buff;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ ptr2 = gvsub2str(ptr, &opstr, FALSE);
gv_target = gvt1; /* restore "gv_target" */
tmp_mval.mvtype = MV_STR;
tmp_mval.str.addr = (char *)buff;
@@ -420,7 +423,9 @@ void op_merge(void)
LV_SBS_DEPTH(dst_lv, is_base_var, sbs_depth);
if (MAX_LVSUBSCRIPTS <= sbs_depth)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_MERGEINCOMPL, 0, ERR_MAXNRSUBSCRIPTS);
- ptr2 = gvsub2str(ptr, buff, FALSE);
+ opstr.addr = (char *)buff;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ ptr2 = gvsub2str(ptr, &opstr, FALSE);
subsc->mvtype = MV_STR;
subsc->str.addr = (char *)buff;
subsc->str.len = INTCAST(ptr2 - buff);
@@ -438,22 +443,15 @@ void op_merge(void)
dst_lv->v = *value;
}
gvname_env_restore(gblp2); /* naked indicator is restored into gv_currkey */
+ /* If it so happens $data(^gvn2) was non-zero at start of op_merge but after the check it became zero,
+ * $data(dst_lv) will be 0 so needs active_lv clearing.
+ */
+ UNDO_ACTIVE_LV(actlv_op_merge2); /* kill "dst" and parents as applicable if $data(dst)=0 */
POP_MV_STENT(); /* subsc */
}
POP_MV_STENT(); /* mkey */
} else
{ /* source is local */
- op_fndata(mglvnp->lclp[IND2], value);
- dollardata_src = MV_FORCE_INT(value);
- if (0 == dollardata_src)
- {
- UNDO_ACTIVE_LV;
- POP_MV_STENT(); /* value */
- if (MARG1_IS_GBL(merge_args))
- gvname_env_restore(gblp1); /* store destination as naked indicator in gv_currkey */
- merge_args = 0; /* Must reset to zero to reuse the Global */
- return;
- }
/* not memsetting output to 0 here can cause garbage value of output.out_var.lv.child which in turn can
* cause a premature return from lvzwr_var resulting in op_merge() returning without having done the merge.
*/
@@ -462,39 +460,43 @@ void op_merge(void)
{ /*==================== MERGE lvn1=lvn2 =====================*/
assert(mglvnp->lclp[IND1]);
/* if self merge then NOOP */
- if (!merge_desc_check()) /* will not proceed if one is descendant of another */
+ if (merge_desc_check()) /* will not proceed if one is descendant of another */
{
- POP_MV_STENT(); /* value */
- merge_args = 0; /* Must reset to zero to reuse the Global */
- return;
+ output.buff = (char *)buff;
+ output.ptr = output.buff;
+ output.out_var.lv.lvar = mglvnp->lclp[IND1];
+ zwr_output = &output;
+ lvzwr_init(zwr_patrn_mident, &mglvnp->lclp[IND2]->v);
+ lvzwr_arg(ZWRITE_ASTERISK, 0, 0);
+ lvzwr_var(mglvnp->lclp[IND2], 0);
+# ifdef DEBUG
+ /* assert that destination got all data of the source and its descendants */
+ op_fndata(mglvnp->lclp[IND2], value);
+ dollardata_src = MV_FORCE_INT(value);
+ op_fndata(mglvnp->lclp[IND1], value);
+ dollardata_dst = MV_FORCE_INT(value);
+ assert((dollardata_src & dollardata_dst) == dollardata_src);
+# endif
}
- output.buff = (char *)buff;
- output.ptr = output.buff;
- output.out_var.lv.lvar = mglvnp->lclp[IND1];
- zwr_output = &output;
- lvzwr_init(zwr_patrn_mident, &mglvnp->lclp[IND2]->v);
- lvzwr_arg(ZWRITE_ASTERISK, 0, 0);
- lvzwr_var(mglvnp->lclp[IND2], 0);
- /* assert that destination got all data of the source and its descendants */
- DEBUG_ONLY(op_fndata(mglvnp->lclp[IND1], value));
- DEBUG_ONLY(dollardata_dst = MV_FORCE_INT(value));
- assert((dollardata_src & dollardata_dst) == dollardata_src);
} else
{ /*==================== MERGE ^gvn1=lvn2 =====================*/
assert(MARG1_IS_GBL(merge_args) && MARG2_IS_LCL(merge_args));
- gvname_env_save(gblp1);
- key = gblp1->s_gv_currkey;
- GET_NSUBS_IN_GVKEY(key->base, key->end - 1, gvn1subs); /* sets "gvn1subs" */
- gblp1->gvkey_nsubs = gvn1subs; /* used later in lvzwr_out */
- output.buff = (char *)buff;
- output.ptr = output.buff;
- output.out_var.gv.end = gv_currkey->end;
- output.out_var.gv.prev = gv_currkey->prev;
- zwr_output = &output;
- lvzwr_init(zwr_patrn_mident, &mglvnp->lclp[IND2]->v);
- lvzwr_arg(ZWRITE_ASTERISK, 0, 0);
- lvzwr_var(mglvnp->lclp[IND2], 0);
- gvname_env_restore(gblp1); /* store destination as naked indicator in gv_currkey */
+ if (NULL != mglvnp->lclp[IND2])
+ { /* source is defined */
+ gvname_env_save(gblp1);
+ key = gblp1->s_gv_currkey;
+ GET_NSUBS_IN_GVKEY(key->base, key->end - 1, gvn1subs); /* sets "gvn1subs" */
+ gblp1->gvkey_nsubs = gvn1subs; /* used later in lvzwr_out */
+ output.buff = (char *)buff;
+ output.ptr = output.buff;
+ output.out_var.gv.end = gv_currkey->end;
+ output.out_var.gv.prev = gv_currkey->prev;
+ zwr_output = &output;
+ lvzwr_init(zwr_patrn_mident, &mglvnp->lclp[IND2]->v);
+ lvzwr_arg(ZWRITE_ASTERISK, 0, 0);
+ lvzwr_var(mglvnp->lclp[IND2], 0);
+ gvname_env_restore(gblp1); /* store destination as naked indicator in gv_currkey */
+ }
}
}
POP_MV_STENT(); /* value */
diff --git a/sr_port/op_merge_arg.c b/sr_port/op_merge_arg.c
index 8f12c25..7849a06 100644
--- a/sr_port/op_merge_arg.c
+++ b/sr_port/op_merge_arg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -64,16 +64,16 @@ GBLREF merge_glvn_ptr mglvnp;
GBLREF gd_region *gv_cur_region;
GBLREF gv_key *gv_currkey;
+error_def(ERR_UNIMPLOP);
+error_def(ERR_TEXT);
+error_def(ERR_GVIS);
+
void op_merge_arg(int m_opr_type, lv_val *lvp)
{
int maxkeysz;
unsigned char buff[MAX_ZWR_KEY_SZ], *end;
char *err_str;
- error_def(ERR_UNIMPLOP);
- error_def(ERR_TEXT);
- error_def(ERR_GVIS);
-
if (!mglvnp)
{
mglvnp = (merge_glvn_ptr) malloc(SIZEOF(struct merge_glvn_struct_type));
@@ -113,19 +113,19 @@ void op_merge_arg(int m_opr_type, lv_val *lvp)
* operation won't work */
assert(dba_cm == gv_cur_region->dyn.addr->acc_meth); /* we should've covered all access methods */
end = format_targ_key(buff, MAX_ZWR_KEY_SZ, gv_currkey, TRUE);
- rts_error(VARLSTCNT(14) ERR_UNIMPLOP, 0,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(14) ERR_UNIMPLOP, 0,
ERR_TEXT, 2, LEN_AND_LIT("GT.CM server does not support MERGE operation"),
ERR_GVIS, 2, end - buff, buff,
ERR_TEXT, 2, REG_LEN_STR(gv_cur_region));
}
break;
default:
- GTMASSERT;
+ assertpro(FALSE);
}
- assert ((merge_args == (MARG1_LCL | MARG2_LCL)) ||
- (merge_args == (MARG1_LCL | MARG2_GBL)) ||
- (merge_args == (MARG1_GBL | MARG2_LCL)) ||
- (merge_args == (MARG1_GBL | MARG2_GBL)) ||
- (merge_args == MARG2_GBL) ||
- (merge_args == MARG2_LCL));
+ assert ((merge_args == (MARG1_LCL | MARG2_LCL))
+ || (merge_args == (MARG1_LCL | MARG2_GBL))
+ || (merge_args == (MARG1_GBL | MARG2_LCL))
+ || (merge_args == (MARG1_GBL | MARG2_GBL))
+ || (merge_args == MARG2_GBL)
+ || (merge_args == MARG2_LCL));
}
diff --git a/sr_port/op_newintrinsic.c b/sr_port/op_newintrinsic.c
index 5fec53d..b06d12c 100644
--- a/sr_port/op_newintrinsic.c
+++ b/sr_port/op_newintrinsic.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -51,7 +51,7 @@ error_def(ERR_NOZTRAPINTRIG);
void op_newintrinsic(int intrtype)
{
mval *intrinsic;
- boolean_t stored_explicit_null;
+ boolean_t stored_explicit_null, etrap_was_active;
switch (intrtype)
{
@@ -60,20 +60,6 @@ void op_newintrinsic(int intrtype)
if (0 < gtm_trigger_depth)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOZTRAPINTRIG);
# endif
- /* Due to the potential intermix of $ETRAP and $ZTRAP, we put a condition on the
- explicit NEWing of these two special variables. If "the other" trap handler
- definition is not null (meaning this handler is not in control) then we will
- ignore the NEW. This is necessary for example when a frame with $ZT set calls
- a routine that NEWs and sets $ET. When it unwinds, we don't want it to pop off
- the old "null" value for $ET which then triggers the nulling out of our current
- $ZT value. Note that op_svput no longer calls this routine for "implicit" NEWs
- but calls directly to gtm_newintrinsic instead.
- */
- if (dollar_etrap.str.len)
- {
- assert(FALSE == ztrap_explicit_null);
- return;
- }
assert(!ztrap_explicit_null || (0 == dollar_ztrap.str.len));
DEBUG_ONLY(stored_explicit_null = FALSE;)
if (ztrap_explicit_null && (0 == dollar_ztrap.str.len))
@@ -81,16 +67,13 @@ void op_newintrinsic(int intrtype)
DEBUG_ONLY(stored_explicit_null = TRUE;)
dollar_ztrap.str.len = STACK_ZTRAP_EXPLICIT_NULL; /* to be later used by unw_mv_ent() */
}
- intrinsic = &dollar_ztrap;
- break;
+ /* Intentionally omitted the "break" here */
case SV_ETRAP:
- /* See comment above for SV_ZTRAP */
- if (dollar_ztrap.str.len)
- {
- assert(FALSE == ztrap_explicit_null);
- return;
- }
- intrinsic = &dollar_etrap;
+ /* Save the active error trap to the stack if either of them is new'ed */
+ if (etrap_was_active = ETRAP_IN_EFFECT)
+ intrinsic = &dollar_etrap;
+ else
+ intrinsic = &dollar_ztrap;
break;
case SV_ESTACK:
intrinsic = &dollar_estack_delta;
@@ -110,7 +93,16 @@ void op_newintrinsic(int intrtype)
assertpro(FALSE && intrtype);
}
gtm_newintrinsic(intrinsic);
- if (SV_ESTACK == intrtype)
+ if (SV_ZTRAP == intrtype)
+ {
+ ztrap_explicit_null = TRUE;
+ if(etrap_was_active)
+ NULLIFY_TRAP(dollar_etrap)
+ } else if (SV_ETRAP == intrtype) {
+ ztrap_explicit_null = FALSE;
+ if(!etrap_was_active)
+ NULLIFY_TRAP(dollar_ztrap)
+ } else if (SV_ESTACK == intrtype)
{ /* Some extra processing for new of $ETRAP:
The delta from $zlevel we keep for estack is kept in an mval for sake of
ease -- gtm_newintrinic knows how to save, new and restore an mval -- but
diff --git a/sr_port/op_newvar.c b/sr_port/op_newvar.c
index caeec16..ad116e3 100644
--- a/sr_port/op_newvar.c
+++ b/sr_port/op_newvar.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include "lv_val.h"
#include <rtnhdr.h>
#include "mv_stent.h"
@@ -34,8 +35,12 @@ GBLREF tp_frame *tp_pointer;
GBLREF symval *curr_symval;
GBLREF uint4 dollar_tlevel;
+error_def(ERR_STACKOFLOW);
+error_def(ERR_STACKCRIT);
+
/* Note this module follows the same basic pattern as gtm_newintrisic which handles
- the same function but for intrinsic vars instead of local vars. */
+ * the same function but for intrinsic vars instead of local vars.
+ */
void op_newvar(uint4 arg1)
{
mv_stent *mv_st_ent, *mvst_tmp, *mvst_prev;
@@ -50,20 +55,17 @@ void op_newvar(uint4 arg1)
int4 shift_size;
DBGRFCT_ONLY(mident_fixed vname;)
- error_def(ERR_STACKOFLOW);
- error_def(ERR_STACKCRIT);
-
varname = &(((var_tabent *)frame_pointer->vartab_ptr)[arg1]);
tabent = lookup_hashtab_mname(&curr_symval->h_symtab, varname);
assert(tabent); /* variable must be defined and fetched by this point */
if (frame_pointer->type & SFT_COUNT)
{ /* Current (youngest) frame IS a counted frame.
- If the var being new'd exists in an earlier frame, we need to save
- that value so it can be restored when we exit this frame. Since this
- is a counted frame, just create a stack entry to save the old value.
- If there was no previous entry, we will destroy the entry when we pop
- off this frame (make it undefined again).
- */
+ * If the var being new'd exists in an earlier frame, we need to save
+ * that value so it can be restored when we exit this frame. Since this
+ * is a counted frame, just create a stack entry to save the old value.
+ * If there was no previous entry, we will destroy the entry when we pop
+ * off this frame (make it undefined again).
+ */
if (!(frame_pointer->flags & SFF_INDCE))
{ /* This is a normal counted frame with a stable variable name pointer */
PUSH_MV_STENT(MVST_PVAL);
@@ -72,10 +74,10 @@ void op_newvar(uint4 arg1)
ptab = &mv_st_ent->mv_st_cont.mvs_pval.mvs_ptab;
} else
{ /* This is actually an indirect (likely XECUTE or ZINTERRUPT) so the varname
- pointer could be gone by the time we unroll this frame if an error occurs
- while this frame is executing and error processing marks this frame reusable
- so carry the name along with us to avoid this situation.
- */
+ * pointer could be gone by the time we unroll this frame if an error occurs
+ * while this frame is executing and error processing marks this frame reusable
+ * so carry the name along with us to avoid this situation.
+ */
PUSH_MV_STENT(MVST_NVAL);
mv_st_ent = mv_chain;
new = mv_st_ent->mv_st_cont.mvs_nval.mvs_val = lv_getslot(curr_symval);
@@ -86,13 +88,13 @@ void op_newvar(uint4 arg1)
assert((int)arg1 >= 0);
} else
{ /* Current (youngest) frame IS NOT a counted frame.
- The situation is more complex because this is not a true stackframe.
- It has full access to the base "counted" frame's vars and any new
- done here must behave as if it were done in the base/counted frame.
- To accomplish this, we actually find the base frame we are executing
- in, then shift all frames younger than that up by the size of the mvstent
- entry we need to save/restore the value being new'd and then go into
- each frame modified and fixup all the addresses.
+ * The situation is more complex because this is not a true stackframe.
+ * It has full access to the base "counted" frame's vars and any new
+ * done here must behave as if it were done in the base/counted frame.
+ * To accomplish this, we actually find the base frame we are executing
+ * in, then shift all frames younger than that up by the size of the mvstent
+ * entry we need to save/restore the value being new'd and then go into
+ * each frame modified and fixup all the addresses.
*/
fp = frame_pointer;
fp_prev = fp->old_frame_pointer;
@@ -105,29 +107,28 @@ void op_newvar(uint4 arg1)
assert(fp_prev);
}
/* top is beginning of earliest indirect stackframe before counted base frame.
- It is the point where we will shift to make room to insert an mv_stent into
- the base frame.
+ * It is the point where we will shift to make room to insert an mv_stent into
+ * the base frame.
*/
top = (unsigned char *)(fp + 1);
old_sp = msp;
shift_size = mvs_size[MVST_NVAL];
msp -= shift_size;
if (msp <= stackwarn)
- {
+ {
if (msp <= stacktop)
{
msp = old_sp;
- rts_error(VARLSTCNT(1) ERR_STACKOFLOW);
- }
- else
- rts_error(VARLSTCNT(1) ERR_STACKCRIT);
- }
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKOFLOW);
+ } else
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKCRIT);
+ }
/* Ready, set, shift the younger indirect frames to make room for mv_stent */
memmove(msp, old_sp, top - (unsigned char *)old_sp);
mv_st_ent = (mv_stent *)(top - shift_size);
mv_st_ent->mv_st_type = MVST_NVAL;
ADJUST_FRAME_POINTER(frame_pointer, shift_size);
- /* adjust all the pointers in all the stackframes that were moved */
+ /* Adjust all the pointers in all the stackframes that were moved */
for (fp_fix = frame_pointer; fp_fix != fp_prev; fp_fix = fp_fix->old_frame_pointer)
{
if ((unsigned char *)fp_fix->l_symtab < top && (unsigned char *)fp_fix->l_symtab > stacktop)
@@ -149,7 +150,8 @@ void op_newvar(uint4 arg1)
if ((unsigned char *)tpp->fp > stacktop)
tpp->fp = (struct stack_frame_struct *)((char *)tpp->fp - shift_size);
/* Note low check for < top may be superfluous here but without a test case to verify, I
- feel better leaving it in. SE 8/2001 */
+ * feel better leaving it in. SE 8/2001
+ */
if ((unsigned char *)tpp->mvc < top && (unsigned char *)tpp->mvc > stacktop)
tpp->mvc = (struct mv_stent_struct *)((char *)tpp->mvc - shift_size);
}
@@ -160,8 +162,8 @@ void op_newvar(uint4 arg1)
mv_chain = mv_st_ent;
} else
{ /* One of the indirect frames has mv_stents associated with it so we have to find
- the appropriate insertion point for this frame.
- */
+ * the appropriate insertion point for this frame.
+ */
fp = (stack_frame *)((char *)fp - shift_size);
mv_chain = (mv_stent *)((char *)mv_chain - shift_size);
mvst_tmp = mv_chain;
@@ -179,11 +181,9 @@ void op_newvar(uint4 arg1)
DEBUG_ONLY(mv_st_ent->mv_st_cont.mvs_nval.name = ((var_tabent *)frame_pointer->vartab_ptr)[arg1]);
DEBUG_ONLY(varname = &mv_st_ent->mv_st_cont.mvs_nval.name);
}
-
- /* initialize new data cell */
+ /* Initialize new data cell */
LVVAL_INIT(new, curr_symval);
-
- /* finish initializing restoration structures */
+ /* Finish initializing restoration structures */
ptab->save_value = (lv_val *)tabent->value;
ptab->hte_addr = tabent;
DEBUG_ONLY(ptab->nam_addr = varname);
diff --git a/sr_port/op_putindx.c b/sr_port/op_putindx.c
index f7fe905..dae7403 100644
--- a/sr_port/op_putindx.c
+++ b/sr_port/op_putindx.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,6 +16,7 @@
#include "gtm_string.h"
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "collseq.h"
#include "stringpool.h"
@@ -35,18 +36,63 @@
#include "stack_frame.h"
#ifdef DEBUG
#include "gtm_ctype.h"
+#include "trans_numeric.h"
#endif
-GBLDEF lv_val *active_lv;
+#ifdef DEBUG
+#define ACTIVELV_DBG_ARRAY_SIZE_DEF 64
+#endif
GBLREF symval *curr_symval;
GBLREF stack_frame *frame_pointer;
GBLREF bool undef_inhibit;
+#ifdef DEBUG
+GBLREF lv_val *active_lv;
+#endif
error_def(ERR_LVNULLSUBS);
error_def(ERR_MAXSTRLEN);
error_def(ERR_UNDEF);
+#ifdef DEBUG
+void set_active_lv(lv_val *newlv, boolean_t do_assert, int type)
+{
+ activelv_dbg_t *dbg_array;
+ int lv_index;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ if (NULL == (dbg_array = TREF(activelv_dbg_array)))
+ {
+ TREF(activelv_dbg_array) = (activelv_dbg_t *)malloc(ACTIVELV_DBG_ARRAY_SIZE_DEF * SIZEOF(activelv_dbg_t));
+ dbg_array = TREF(activelv_dbg_array);
+ }
+ if (do_assert)
+ ASSERT_ACTIVELV_GOOD(active_lv);
+ if (NULL != newlv)
+ assert(!LV_IS_BASE_VAR(newlv)); /* active_lv should never be set to a base variable */
+ lv_index = TREF(activelv_index);
+ assert((0 <= lv_index) && (ACTIVELV_DBG_ARRAY_SIZE_DEF > lv_index));
+ if ((active_lv != newlv) || (0 == TREF(activelv_cycle)))
+ {
+ (TREF(activelv_cycle))++;
+ (TREF(activelv_index))++;
+ if (ACTIVELV_DBG_ARRAY_SIZE_DEF == TREF(activelv_index))
+ TREF(activelv_index) = 0;
+ dbg_array[lv_index].active_lv = active_lv;
+ dbg_array[lv_index].newlv = newlv;
+ dbg_array[lv_index].count = 0;
+ } else
+ dbg_array[lv_index].count++;
+ dbg_array[lv_index].type = type;
+ dbg_array[lv_index].frame_pointer = frame_pointer;
+ dbg_array[lv_index].curr_symval = curr_symval;
+ dbg_array[lv_index].mpc = frame_pointer->mpc;
+ dbg_array[lv_index].ctxt = frame_pointer->ctxt;
+ active_lv = newlv;
+}
+#endif
+
lv_val *op_putindx(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...)
{
boolean_t is_canonical, is_base_var;
@@ -57,6 +103,7 @@ lv_val *op_putindx(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...)
lvTree *lvt;
lvTreeNode *parent;
lv_val *base_lv;
+ DEBUG_ONLY(int orig_subs_level;)
VMS_ONLY(int argcnt;)
DCL_THREADGBL_ACCESS;
@@ -84,6 +131,7 @@ lv_val *op_putindx(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...)
lv = start;
assert(NULL != lv);
LV_SBS_DEPTH(start, is_base_var, subs_level);
+ DEBUG_ONLY(orig_subs_level = subs_level;)
for (subs_level++; --argcnt > 0; subs_level++)
{
key = va_arg(var, mval *);
@@ -96,9 +144,8 @@ lv_val *op_putindx(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...)
{
if (LVNULLSUBS_OK != TREF(lv_null_subs)) /* Error for both LVNULLSUBS_{NO,NEVER} */
{
- active_lv = lv;
va_end(var);
- rts_error(VARLSTCNT(1) ERR_LVNULLSUBS);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_LVNULLSUBS);
}
}
if (TREF(local_collseq))
@@ -147,17 +194,25 @@ lv_val *op_putindx(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...)
{
lv = (lv_val *)lvAvlTreeNodeInsert(lvt, key, parent);
lv->v.mvtype = 0; /* initialize mval to undefined value at this point */
+ /* maintain active_lv so we free this lv_val (and parent lv_vals as appropriate) in case of a
+ * runtime error (e.g. UNDEF or LVNULLSUBS) in this for loop.
+ */
+ SET_ACTIVE_LV(lv, (orig_subs_level == (subs_level + 1)) ? TRUE : FALSE, actlv_op_putindx1);
}
}
va_end(var);
- /* This var is about to be set/modified. If it exists and is an alias container var,
- * that reference is going to go away. Take care of that possibility now.
- */
- if (LV_IS_VAL_DEFINED(lv))
+ if (base_lv != lv)
{
- DECR_AC_REF(lv, TRUE);
- lv->v.mvtype &= ~MV_ALIASCONT; /* Value being replaced is now no longer a container var */
+ /* This var is about to be set/modified. If it exists and is an alias container var,
+ * that reference is going to go away. Take care of that possibility now.
+ */
+ if (LV_IS_VAL_DEFINED(lv))
+ {
+ DECR_AC_REF(lv, TRUE);
+ lv->v.mvtype &= ~MV_ALIASCONT; /* Value being replaced is now no longer a container var */
+ }
+ assert(NULL != lv);
+ SET_ACTIVE_LV(lv, (orig_subs_level == (subs_level + 1)) ? TRUE : FALSE, actlv_op_putindx2);
}
- active_lv = lv;
return lv;
}
diff --git a/sr_port/op_rhdaddr.c b/sr_port/op_rhdaddr.c
index 0f96c43..c008eef 100644
--- a/sr_port/op_rhdaddr.c
+++ b/sr_port/op_rhdaddr.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,16 +19,21 @@
GBLREF mident_fixed zlink_mname;
GBLREF rtn_tabent *rtn_names;
+#ifdef USHBIN_SUPPORTED
+LITDEF mval literal_null;
+#endif
+
error_def(ERR_ZLINKFILE);
error_def(ERR_ZLMODULE);
/* For routine name given, return routine header address if rhd not already set */
rhdtyp *op_rhdaddr(mval *name, rhdtyp *rhd)
{
- if (NULL != rhd)
- return rhd;
- else
- return op_rhdaddr1(name);
+# ifdef USHBIN_SUPPORTED
+ return op_rhd_ext(name, (mval *)&literal_null, rhd, NULL);
+# else
+ return (NULL != rhd) ? rhd : op_rhdaddr1(name);
+# endif
}
/* Find the newest linked version of a routine */
@@ -59,5 +64,13 @@ rhdtyp *op_rhdaddr1(mval *name)
ERR_ZLMODULE, 2, strlen(&zlink_mname.c[0]), zlink_mname.c);
# endif
}
+# ifdef USHBIN_SUPPORTED
+ /* In this (autorelink) context, no need to pass 4th arg (*lnr) since other opcodes used in conjunction with
+ * op_rhdaddr1 will handle label offset if necessary.
+ */
+ return op_rhd_ext(&routine, (mval *)&literal_null, answer, NULL);
+# else
+ /* Non-autorelink context just returns the routine header address */
return answer;
+# endif
}
diff --git a/sr_port/op_rterror.c b/sr_port/op_rterror.c
index a2df35e..5165e09 100644
--- a/sr_port/op_rterror.c
+++ b/sr_port/op_rterror.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,19 +12,19 @@
#include "mdef.h"
#include "op.h"
+error_def(ERR_LABELNOTFND);
+
void op_rterror(int4 sig, boolean_t subrtn)
{
- /* If this module is called as an M subroutine, the message we generate
- will not have the correct M line-of-code reference because (1) we have
- already created the stackframe for the subroutine call we are not now
- going to make and (2) the code generator puts the code to call us
- at the end of the module. Therefore the Mref generated will be the last line
- in the module. To get around this, if this is a subroutine/function call
- we will unwind this (bogus) frame prior to making the error call so the
- M reference in the error message will be the actual subroutine call itself
- instead of the last physical line of the module. Inline calls will not
- do an unwind().
- */
- if (subrtn) op_unwind();
- rts_error(VARLSTCNT(2) sig, 0);
+ /* If this module is called as an M subroutine, the message we generate will not have the correct M line-of-code reference
+ * because (1) we have already created the stackframe for the subroutine call we are not now going to make and (2) the code
+ * generator puts the code to call us at the end of the module. Therefore the Mref generated will be the last line in the
+ * module. To get around this, if this is a subroutine/function call we will unwind this (bogus) frame prior to making the
+ * error call so the M reference in the error message will be the actual subroutine call itself instead of the last
+ * physical line of the module. Inline calls will not do an unwind() based on the distinguished error for GOTO or the
+ * subrtn flag.
+ */
+ if (subrtn && (ERR_LABELNOTFND != sig))
+ op_unwind();
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) sig, 0);
}
diff --git a/sr_port/op_savlvn.c b/sr_port/op_savlvn.c
index b07f5c1..d0a0357 100644
--- a/sr_port/op_savlvn.c
+++ b/sr_port/op_savlvn.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -70,6 +70,7 @@ void op_savlvn(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...)
for (i = 0; i < argcnt; i++, m++)
{ /* now all the pieces of the key */
key = va_arg(var, mval *);
+ MV_FORCE_DEFINED(key);
*m = *key;
lvn_info->lv_subs[i] = m;
(TREF(glvn_pool_ptr))->mval_top++;
diff --git a/sr_port/op_setals2als.c b/sr_port/op_setals2als.c
index f155c0b..5bdc42d 100644
--- a/sr_port/op_setals2als.c
+++ b/sr_port/op_setals2als.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
@@ -28,7 +29,6 @@
GBLREF stack_frame *frame_pointer;
GBLREF symval *curr_symval;
GBLREF uint4 dollar_tlevel;
-GBLREF lv_val *active_lv;
/* Operation - The destination variable becomes a new alias of the source variable:
* 1) Index into the variable name table to get the variable name for the new alias (destination).
@@ -45,6 +45,8 @@ void op_setals2als(lv_val *srclv, int destindx)
lv_val *dstlv;
boolean_t added;
+ SET_ACTIVE_LV(NULL, TRUE, actlv_op_setals2als); /* If we get here, subscript set was successful.
+ * Clear active_lv to avoid later cleanup issues */
assert(srclv);
assert(LV_IS_BASE_VAR(srclv)); /* Verify base var */
DEBUG_ONLY(added = FALSE);
@@ -81,6 +83,4 @@ void op_setals2als(lv_val *srclv, int destindx)
tabent->value = (void *)srclv;
INCR_TREFCNT(srclv);
MARK_ALIAS_ACTIVE(LV_SYMVAL(srclv)->symvlvl); /* This symval has had alias activity */
- active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful. clear active_lv to avoid later
- cleanup problems */
}
diff --git a/sr_port/op_setalsct2alsct.c b/sr_port/op_setalsct2alsct.c
index 1cdf82a..e6dc86a 100644
--- a/sr_port/op_setalsct2alsct.c
+++ b/sr_port/op_setalsct2alsct.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,6 +13,7 @@
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "op.h"
#include "lv_val.h"
#include "gdsroot.h"
@@ -22,26 +23,26 @@
#include "gdsfhead.h"
#include "alias.h"
#include "min_max.h"
+#include <rtnhdr.h>
+#include "stack_frame.h"
GBLREF symval *curr_symval;
GBLREF uint4 dollar_tlevel;
-/* Operation - Copy alias container to another alias container
- * Note that this cannot happen as the result of a normal copy via regular SET command (we do not allow it).
- */
+error_def(ERR_ALIASEXPECTED);
+
+/* Operation - Copy alias container to another alias container */
void op_setalsct2alsct(lv_val *srclv, lv_val *dstlv)
{
lv_val *src_lvref, *src_lvbase, *dst_lvbase;
symval *sym_src_lvref, *sym_srclv, *sym_dstlv;
- error_def(ERR_ALIASEXPECTED);
-
assert(srclv);
assert(!LV_IS_BASE_VAR(srclv)); /* Verify subscripted var */
assert(dstlv);
assert(!LV_IS_BASE_VAR(dstlv)); /* Verify subscripted var */
if (!(srclv->v.mvtype & MV_ALIASCONT))
- rts_error(VARLSTCNT(1) ERR_ALIASEXPECTED);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ALIASEXPECTED);
src_lvref = (lv_val *)srclv->v.str.addr;
assert(src_lvref);
assert(LV_IS_BASE_VAR(src_lvref)); /* Verify base var */
diff --git a/sr_port/op_setalsctin2als.c b/sr_port/op_setalsctin2als.c
index 58b80fa..bdd0369 100644
--- a/sr_port/op_setalsctin2als.c
+++ b/sr_port/op_setalsctin2als.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
@@ -29,7 +30,8 @@
GBLREF stack_frame *frame_pointer;
GBLREF symval *curr_symval;
GBLREF uint4 dollar_tlevel;
-GBLREF lv_val *active_lv;
+
+error_def(ERR_ALIASEXPECTED);
/* Operation - The destination variable becomes a new alias of the data pointed to by the source container variable:
*
@@ -50,12 +52,12 @@ void op_setalsctin2als(lv_val *srclv, int destindx)
int4 srcsymvlvl;
boolean_t added;
- error_def(ERR_ALIASEXPECTED);
-
+ SET_ACTIVE_LV(NULL, TRUE, actlv_op_setalsctin2als); /* If we get here, subscript set was successful.
+ * Clear active_lv to avoid later cleanup issues */
assert(srclv);
assert(!LV_IS_BASE_VAR(srclv)); /* Verify subscripted var */
if (!(srclv->v.mvtype & MV_ALIASCONT))
- rts_error(VARLSTCNT(1) ERR_ALIASEXPECTED);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ALIASEXPECTED);
srclvc = (lv_val *)srclv->v.str.addr;
assert(srclvc);
assert(LV_IS_BASE_VAR(srclvc)); /* Verify base var */
@@ -84,7 +86,9 @@ void op_setalsctin2als(lv_val *srclv, int destindx)
}
/* Note dstlv could still be NULL if this is the first assignment to the target and the var is not being TPSAVed */
assert(dstlv != srclv); /* Since source is container, this is an impossible situation */
- INCR_TREFCNT(srclvc); /* Increment before dstlv processing to prevent removal of last reference to srclvc */
+ INCR_TREFCNT(srclvc); /* Increment before dstlv processing to prevent removal of last reference to srclvc. This is
+ * also the trefcnt bump since srclv is now in the hash table (symval).
+ */
if (dstlv)
{
assert(LV_IS_BASE_VAR(dstlv)); /* Verify base var */
@@ -106,6 +110,4 @@ void op_setalsctin2als(lv_val *srclv, int destindx)
tabent->value = (void *)srclvc;
/* These symvals have had alias activity */
MARK_ALIAS_ACTIVE(MIN(srcsymvlvl, LV_SYMVAL(srclvc)->symvlvl));
- active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful. clear active_lv to avoid later
- cleanup problems */
}
diff --git a/sr_port/op_setalsin2alsct.c b/sr_port/op_setalsin2alsct.c
index 17fbf41..aa9209c 100644
--- a/sr_port/op_setalsin2alsct.c
+++ b/sr_port/op_setalsin2alsct.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2011 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
diff --git a/sr_port/op_setfnretin2als.c b/sr_port/op_setfnretin2als.c
index 89283ac..a836b3b 100644
--- a/sr_port/op_setfnretin2als.c
+++ b/sr_port/op_setfnretin2als.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,7 @@
#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
@@ -29,7 +30,6 @@
GBLREF stack_frame *frame_pointer;
GBLREF symval *curr_symval;
GBLREF uint4 dollar_tlevel;
-GBLREF lv_val *active_lv;
GBLREF mval *alias_retarg;
/* Operation - The destination variable becomes a new alias of the data pointed to by the source container variable:
@@ -60,6 +60,8 @@ void op_setfnretin2als(mval *srcmv, int destindx)
int4 srcsymvlvl;
boolean_t added;
+ SET_ACTIVE_LV(NULL, TRUE, actlv_op_setfnretin2als); /* If we get here, subscript set was successful.
+ * Clear active_lv to avoid later cleanup issues */
assert(alias_retarg == srcmv);
assert(srcmv);
assert(srcmv->mvtype & MV_ALIASCONT);
@@ -118,7 +120,5 @@ void op_setfnretin2als(mval *srcmv, int destindx)
* symtab which popped during the return.
*/
MARK_ALIAS_ACTIVE(MIN(srcsymvlvl, LV_SYMVAL(srclvc)->symvlvl));
- active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful. clear active_lv to avoid later
- cleanup problems */
alias_retarg = NULL;
}
diff --git a/sr_port/op_setfnretin2alsct.c b/sr_port/op_setfnretin2alsct.c
index 8f6b1df..2c57ba9 100644
--- a/sr_port/op_setfnretin2alsct.c
+++ b/sr_port/op_setfnretin2alsct.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,6 +13,7 @@
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "op.h"
#include "lv_val.h"
#include "gdsroot.h"
diff --git a/sr_port/op_setzbrk.c b/sr_port/op_setzbrk.c
index 8d8a6c0..7720e3e 100644
--- a/sr_port/op_setzbrk.c
+++ b/sr_port/op_setzbrk.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -79,7 +79,7 @@ void op_setzbrk(mval *rtn, mval *lab, int offset, mval *act, int cnt)
zr_init(&zbrk_recs, INIT_NUM_ZBREAKS);
}
if (CANCEL_ALL == cnt)
- zr_remove(NULL, NOBREAKMSG);
+ zr_remove_zbrks(NULL, NOBREAKMSG);
else
{
GTMTRIG_ONLY(IS_TRIGGER_RTN(&rtn->str, is_trigger));
@@ -145,7 +145,7 @@ void op_setzbrk(mval *rtn, mval *lab, int offset, mval *act, int cnt)
if (NULL == (z_ptr = zr_find(&zbrk_recs, addr)))
{
# ifdef USHBIN_SUPPORTED
- if (NULL != routine->shlib_handle && NULL == routine->shared_ptext_adr)
+ if ((NULL != routine->shared_ptext_adr) && (routine->shared_ptext_adr == routine->ptext_adr))
{ /* setting a breakpoint in a shared routine, need to make a private copy */
addr_off = (unsigned char *)addr - routine->ptext_adr;
if (SS_NORMAL == (status = cre_private_code_copy(routine)))
diff --git a/sr_port/op_stoglvn.c b/sr_port/op_stoglvn.c
index 284fcfa..e4ac689 100644
--- a/sr_port/op_stoglvn.c
+++ b/sr_port/op_stoglvn.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -39,12 +39,18 @@ void op_stoglvn(uint4 indx, mval *value)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
+ MV_FORCE_DEFINED(value); /* do what op_sto.s does */
oc = (TREF(glvn_pool_ptr))->slot[indx].sav_opcode;
if (OC_SAVLVN == oc)
{ /* lvn */
lv = op_rfrshlvn(indx, OC_PUTINDX);
+ /* Below two lines do what op_sto.s does. Ideally we should be invoking op_sto from here but
+ * it is not easily possible due to op_sto expecting its arguments in registers which this
+ * C function cannot ensure. Any changes to op_sto.s might need to be correspondingly made here.
+ */
lv->v = *value;
- } else if (OC_NOOP != oc) /* if indirect error blew set up, skip this */
+ lv->v.mvtype &= ~MV_ALIASCONT; /* Make sure alias container property does not pass */
+ } else if (OC_NOOP != oc) /* if indirect error blew set up, skip this */
{ /* gvn */
op_rfrshgvn(indx, oc);
op_gvput(value);
diff --git a/sr_port/op_svput.c b/sr_port/op_svput.c
index 809a574..4f7d2da 100644
--- a/sr_port/op_svput.c
+++ b/sr_port/op_svput.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -197,7 +197,10 @@ void op_svput(int varnum, mval *v)
{
ztrap_explicit_null = FALSE;
if (dollar_etrap.str.len > 0)
+ {
gtm_newintrinsic(&dollar_etrap);
+ NULLIFY_TRAP(dollar_etrap);
+ }
}
if (ztrap_form & ZTRAP_POP)
ztrap_save_ctxt();
@@ -289,10 +292,7 @@ void op_svput(int varnum, mval *v)
dollar_ztrap.mvtype = MV_STR;
dollar_ztrap.str = v->str;
} else if (dollar_ztrap.str.len > 0)
- { /* Ensure that $ETRAP and $ZTRAP are not both active at the same time */
- assert(FALSE == ztrap_explicit_null);
- gtm_newintrinsic(&dollar_ztrap);
- }
+ NULLIFY_TRAP(dollar_ztrap)
ztrap_explicit_null = FALSE;
break;
case SV_ZERROR:
diff --git a/sr_port/op_tcommit.c b/sr_port/op_tcommit.c
index 373f70f..aa1d546 100644
--- a/sr_port/op_tcommit.c
+++ b/sr_port/op_tcommit.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -199,6 +199,9 @@ enum cdb_sc op_tcommit(void)
boolean_t before_image_needed;
boolean_t skip_invoke_restart;
uint4 update_trans;
+# ifdef DEBUG
+ boolean_t forw_recov_lgtrig_only;
+# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -245,7 +248,21 @@ enum cdb_sc op_tcommit(void)
}
)
save_cur_region = gv_cur_region;
- DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
+# ifdef DEBUG
+ if ((NULL != gv_currkey) && (0 != gv_currkey->base[0]) && ((NULL == gv_target) || !gv_target->gvname.var_name.len))
+ { /* This is a case where forward recovery is playing a TLGTRIG/ULGTRIG only transaction,
+ * no other global references. In that case, no gv_bind_name would have happened and so
+ * gv_target could be NULL (because of a MUR_CHANGE_REG done at the start of this transaction)
+ * or gv_target could be equal to csa->dir_tree (done in mur_forward). Assert accordingly.
+ */
+ assert(jgbl.forw_phase_recovery);
+ forw_recov_lgtrig_only = TRUE;
+ } else
+ {
+ DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
+ forw_recov_lgtrig_only = FALSE;
+ }
+# endif
if (NULL != first_sgm_info) /* if (database work in the transaction) */
{
for (temp_si = si = first_sgm_info; (cdb_sc_normal == status) && (NULL != si); si = si->next_sgm_info)
@@ -268,6 +285,20 @@ enum cdb_sc op_tcommit(void)
assert(!is_mm || (0 == si->cr_array_size && NULL == si->cr_array));
/* whenever si->first_cw_set is non-NULL, ensure that si->update_trans is non-zero */
assert((NULL == si->first_cw_set) || si->update_trans);
+ /* If LGTRIG only TP transaction by forward recovery, assert no db blocks */
+# ifdef DEBUG
+ if (forw_recov_lgtrig_only)
+ {
+ jnl_format_buffer *jfb;
+
+ assert(NULL == si->first_cw_set);
+ if (JNL_ENABLED(csa))
+ {
+ for (jfb = si->jnl_head; (NULL != jfb); jfb = jfb->next)
+ GTMTRIG_ONLY(assert(JNL_LGTRIG == jfb->ja.operation));
+ }
+ }
+# endif
/* Whenever si->first_cw_set is NULL, ensure that si->update_trans is FALSE
* except (1) when there are duplicate sets in which case also ensure that if the database
* is journaled, at least one journal record is being written or
@@ -493,7 +524,10 @@ enum cdb_sc op_tcommit(void)
tp_clean_up(FALSE); /* Not the rollback type of cleanup */
gv_cur_region = save_cur_region;
TP_CHANGE_REG(gv_cur_region);
- DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
+# ifdef DEBUG
+ if (!forw_recov_lgtrig_only)
+ DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
+# endif
/* Cancel or clear any pending TP timeout only if real commit (i.e. outermost commit) */
(*tp_timeout_clear_ptr)();
} else /* an intermediate commit */
diff --git a/sr_port/op_tstart.c b/sr_port/op_tstart.c
index 17c96a1..337fc61 100644
--- a/sr_port/op_tstart.c
+++ b/sr_port/op_tstart.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,6 +16,7 @@
#include "gtm_string.h"
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
@@ -45,6 +46,8 @@
#include "longset.h" /* needed for cws_insert.h */
#include "cws_insert.h" /* for cw_stagnate_reinitialized */
#include "alias.h"
+#include "stp_parms.h"
+#include "stringpool.h"
#ifdef GTM_TRIGGER
#include "gtm_trigger_trc.h"
#endif
@@ -93,6 +96,7 @@ GBLREF uint4 tstartcycle;
GBLREF char *update_array_ptr;
GBLREF ua_list *curr_ua, *first_ua;
GBLREF mstr extnam_str;
+GBLREF lv_val *active_lv;
#ifdef GTM_TRIGGER
GBLREF mval dollar_ztwormhole;
GBLREF int4 gtm_trigger_depth;
@@ -139,6 +143,7 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
sgmnt_addrs *csa;
int4 shift_size;
boolean_t tphold_noshift = FALSE, implicit_tstart;
+ lv_val **lvarraycur = NULL, **lvarray = NULL, **lvarraytop, **lvptr;
GTMTRIG_ONLY(boolean_t implicit_trigger;)
DCL_THREADGBL_ACCESS;
@@ -146,8 +151,10 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
implicit_tstart = 0 != (implicit_flag & IMPLICIT_TSTART);
GTMTRIG_ONLY(implicit_trigger = 0 != (implicit_flag & IMPLICIT_TRIGGER_TSTART));
GTMTRIG_ONLY(assert(!implicit_trigger || (implicit_trigger && implicit_tstart)));
- GTMTRIG_ONLY(DBGTRIGR((stderr, "op_tstart: Entered - dollar_tlevel: %d, implicit_flag: %d\n",
- dollar_tlevel, implicit_flag)));
+# if ((defined(GTM_TRIGGER) && defined(DEBUG_TRIGR)) || defined(DEBUG_REFCNT))
+ DBGFPF((stderr, "\n\nop_tstart: Entered - dollar_tlevel: %d, implicit_flag: %d, mpc: 0x"lvaddr"\n", dollar_tlevel,
+ implicit_flag, frame_pointer->mpc));
+# endif
if (implicit_tstart)
/* An implicit op_tstart is being done. In this case, even if we are in direct mode, we want to do
* regular TPHOLD processing (no setting of tphold in the parent frame and shifting of all mv_stents).
@@ -156,9 +163,9 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
*/
tphold_noshift = TRUE;
/* If we haven't done any TP until now, turn the flag on to tell gvcst_init to
- initialize it in any regions it opens from now on and initialize it in any
- regions that are already open.
- */
+ * initialize it in any regions it opens from now on and initialize it in any
+ * regions that are already open.
+ */
if (!tp_in_use)
{
tp_in_use = TRUE;
@@ -169,8 +176,8 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
if (r_local->open && !r_local->was_open &&
(dba_bg == REG_ACC_METH(r_local) || dba_mm == REG_ACC_METH(r_local)))
{ /* Let's initialize those regions but only if it came through gvcst_init_sysops
- (being a bg or mm region)
- */
+ * (being a bg or mm region).
+ */
gvcst_tp_init(r_local);
}
}
@@ -241,6 +248,7 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
tp_reg_free_list = tr; /* Place on free queue */
}
++local_tn; /* Begin new local transaction */
+ INCR_TSTARTCYCLE; /* All local var save/restores operate under this cycle */
tstart_local_tn = local_tn;
/* In journal recovery forward phase, we set jgbl.tp_ztp_jnl_upd_num to whatever update_num the journal record
* has so it is ok for the global variable to be a non-zero value at the start of a TP transaction (possible if
@@ -248,7 +256,6 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
* (in GT.M runtime) we expect it to be 0 at beginning of each TP or ZTP.
*/
assert((0 == jgbl.tp_ztp_jnl_upd_num) || jgbl.forw_phase_recovery);
- INCR_TSTARTCYCLE;
jgbl.wait_for_jnl_hard = TRUE;
GTMTRIG_ONLY(
assert(NULL == jgbl.prev_ztworm_ptr); /* should have been cleared by tp_clean_up of previous TP */
@@ -292,7 +299,7 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
VMS_ONLY(tp_has_kill_t_cse = FALSE;)
assert(!TREF(donot_commit));
}
- /* either cw_stagnate has not been initialized at all or previous-non-TP or tp_hist should have done CWS_RESET */
+ /* Either cw_stagnate has not been initialized at all or previous-non-TP or tp_hist should have done CWS_RESET */
assert((0 == cw_stagnate.size) || cw_stagnate_reinitialized);
if (prescnt > 0)
{
@@ -385,7 +392,7 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
}
/* Add a new tp_frame in the TP stack */
- DBGRFCT((stderr, "\n*** op_tstart: *** Entering $TLEVEL = %d\n", dollar_tlevel + 1));
+ DBGRFCT((stderr, "\n\n********* op_tstart: *** Entering $TLEVEL = %d\n", dollar_tlevel + 1));
tf = (tp_frame *)(tp_sp -= SIZEOF(tp_frame));
assert((unsigned char *)tf > tpstacktop); /* Block should lie entirely within tp stack area */
tf->restart_pc = fp->mpc;
@@ -410,7 +417,7 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
TREF(gv_tporigkey_ptr) = (gv_orig_key_array *)malloc(SIZEOF(gv_orig_key_array));
memset(TREF(gv_tporigkey_ptr), 0, SIZEOF(gv_orig_key_array));
}
- tf->orig_key = (gv_key *)&((TREF(gv_tporigkey_ptr))->gv_orig_key[0]);
+ tf->orig_key = &((TREF(gv_tporigkey_ptr))->gv_orig_key[0]);
assert(NULL != gv_currkey);
MEMCPY_KEY(tf->orig_key, gv_currkey);
tf->gd_header = gd_header;
@@ -433,6 +440,18 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
memcpy(ptr, extnam_str.addr, len);
tf->extnam_str.addr = ptr;
}
+ tf->active_lv = active_lv;
+ if (implicit_tstart && (NULL != active_lv))
+ { /* If active_lv is non-NULL at the start of an implicit TP (possible for example if implicit TP was
+ * started from an op_gvdata call made inside op_merge.c) we should not tamper with this active_lv
+ * as part of the tp_unwind processing of the implicit TP. That active_lv is only for the caller
+ * (op_merge in this case) to play with. So save this active_lv in the TP frame (to be restored
+ * later at commit or rollback time) and set active_lv to NULL for the duration of this TP.
+ * Note: We cannot do this save/restore of active_lv for explicit transactions as those might actually
+ * tamper with active_lv by freeing that memory (e.g. kill * operations).
+ */
+ SET_ACTIVE_LV(NULL, implicit_tstart ? FALSE : TRUE, actlv_op_tstart);
+ }
}
# ifdef DEBUG
else
@@ -448,6 +467,7 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
*/
tf->zgbldir.mvtype = 0; /* impossible value */
tf->extnam_str.len = -1; /* impossible value */
+ tf->active_lv = NULL;
}
# endif
DBG_CHECK_GVTARGET_CSADDRS_IN_SYNC;
@@ -469,24 +489,27 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
tp_pointer = tf;
if (prescnt > 0)
{
+ DBGRFCT((stderr, "\nop_tstart: Beginning processing of varname parameters\n"));
VAR_COPY(lvname, varlst);
for (pres = 0; pres < prescnt; ++pres)
{
preserve = va_arg(lvname, mval *);
/* Note: the assumption (according to the comment below) is that this mval points into the literal table
- and thus could not possibly be undefined. In that case, I do not understand why the earlier loop to
- do MV_FORCE_STR on these variables. Future todo -- verify if that loop is needed. On the assumption
- that it is not, the below assert will verify that the mval is defined to catch any NOUNDEF case.
- */
+ * and thus could not possibly be undefined. In that case, I do not understand why the earlier loop to
+ * do MV_FORCE_STR on these variables. Future todo -- verify if that loop is needed. On the assumption
+ * that it is not, the below assert will verify that the mval is defined to catch any NOUNDEF case.
+ */
assert(MV_DEFINED(preserve));
/* The incoming 'preserve' is the pointer to a literal mval table entry. For the indirect code
* (eg. Direct Mode), since the literal table is no longer on the M stack, we should not shift
- * the incoming va_arg pointer (C9D01-002205) */
+ * the incoming va_arg pointer (C9D01-002205).
+ */
mvname = preserve;
if (0 != mvname->str.len)
{ /* Convert mval to mident and see if it's in the symbol table */
tpvent.var_name.len = mvname->str.len;
tpvent.var_name.addr = mvname->str.addr;
+ DBGRFCT((stderr, "\nop_tstart: Processing var %.*s\n", tpvent.var_name.len, tpvent.var_name.addr));
COMPUTE_HASH_MNAME(&tpvent);
tpvent.marked = FALSE;
if (add_hashtab_mname_symval(&curr_symval->h_symtab, &tpvent, NULL, &tabent))
@@ -497,25 +520,23 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
assert(0 < lv->stats.trefcnt);
assert(lv->stats.crefcnt <= lv->stats.trefcnt);
/* In order to allow restart of a sub-transaction, this should chain rather than back stop,
- with appropriate changes to lv_var_clone and tp_unwind */
+ * with appropriate changes to lv_var_clone and tp_unwind.
+ */
if (NULL == lv->tp_var)
{
TP_SAVE_RESTART_VAR(lv, tf, &tabent->key);
if (LV_HAS_CHILD(lv))
- TPSAV_CNTNRS_IN_TREE(lv);
- } else
- { /* We have saved this var previously. But check if it got saved via a container var
- and therefore has no name associated with it. If so, update the key in the tp_var
- structure so it gets its name restored properly if necessary.
- */
- if (0 == lv->tp_var->key.var_name.len)
- lv->tp_var->key = tabent->key;
+ {
+ ADD_TO_STPARRAY(lv, lvarray, lvarraycur, lvarraytop, lv_val);
+ }
}
}
}
va_end(lvname);
+ DBGRFCT((stderr, "\nop_tstart: Completed processing of varname parameters\n"));
} else if (ALLLOCAL == prescnt)
{ /* Preserve all variables */
+ DBGRFCT((stderr, "\nop_tstart: Beginning processing of all vars due to TSTART *\n"));
tf->tp_save_all_flg = TRUE;
++curr_symval->tp_save_all;
for (curent = curr_symval->h_symtab.base, topent = curr_symval->h_symtab.top; curent < topent; curent++)
@@ -528,21 +549,25 @@ void op_tstart(int implicit_flag, ...) /* value of $T when TSTART */
assert(lv->stats.crefcnt <= lv->stats.trefcnt);
if (NULL == lv->tp_var)
{
+ DBGRFCT((stderr, "\nop_tstart: Creating save point for var '%.*s' at lv_val 0x"lvaddr
+ " and processing any alias containers found in it\n", curent->key.var_name.len,
+ curent->key.var_name.addr, lv));
TP_SAVE_RESTART_VAR(lv, tf, &curent->key);
if (LV_HAS_CHILD(lv))
- TPSAV_CNTNRS_IN_TREE(lv);
- } else
- { /* We have saved this var previously. But check if it got saved via a container var
- and therefore has no name associated with it. If so, update the key in the tp_var
- structure so it gets its name restored properly if necessary.
- */
- if (0 == lv->tp_var->key.var_name.len)
- lv->tp_var->key = curent->key;
+ {
+ ADD_TO_STPARRAY(lv, lvarray, lvarraycur, lvarraytop, lv_val);
+ }
}
}
}
}
va_end(varlst);
+ /* Need to go through list of saved lvs to do tpsav processing for containers in their lv trees */
+ for (lvptr = lvarray; lvptr < lvarraycur; ++lvptr)
+ { /* save *lvptr in local variable before passing to macro to avoid multiple *lvptr references inside macro */
+ lv = *lvptr;
+ TPSAV_CNTNRS_IN_TREE(lv);
+ }
/* Store existing state of locks */
for (pre_lock = mlk_pvt_root; NULL != pre_lock; pre_lock = pre_lock->next)
{
diff --git a/sr_port/op_unwind.c b/sr_port/op_unwind.c
index 2cec65b..fde72e1 100644
--- a/sr_port/op_unwind.c
+++ b/sr_port/op_unwind.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -28,6 +28,11 @@
#include "parm_pool.h"
#include "opcode.h"
#include "glvn_pool.h"
+#include "gdsroot.h"
+#include "gdsblk.h"
+#include "gdsbt.h"
+#include "gdsfhead.h"
+#include "alias.h"
#ifdef GTM_TRIGGER
# include "gtm_trigger_trc.h"
#endif
@@ -61,13 +66,13 @@ void op_unwind(void)
SETUP_THREADGBL_ACCESS;
assert((frame_pointer < frame_pointer->old_frame_pointer) || (NULL == frame_pointer->old_frame_pointer));
if (frame_pointer->type & SFT_COUNT)
- { /* If unwinding a counted frame, make sure we don't have an alias return argument in flight */
- assert(NULL == alias_retarg);
- alias_retarg = NULL;
+ { /* If unwinding a counted frame, make sure we clean up any alias return argument in flight */
+ if (NULL != alias_retarg)
+ CLEAR_ALIAS_RETARG;
}
DBGEHND_ONLY(prevfp = frame_pointer);
if (tp_pointer && tp_pointer->fp <= frame_pointer)
- rts_error(VARLSTCNT(1) ERR_TPQUIT);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TPQUIT);
/* Note that error_ret() should be invoked only after the rts_error() of TPQUIT.
* This is so the TPQUIT error gets noted down in $ECODE (which will not happen if error_ret() is called before).
*/
@@ -103,7 +108,7 @@ void op_unwind(void)
mv_chain = mvc;
msp = (unsigned char *)frame_pointer + SIZEOF(stack_frame);
if (msp > stackbase)
- rts_error(VARLSTCNT(1) ERR_STACKUNDERFLO);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKUNDERFLO);
# ifdef GTM_TRIGGER
if (SFF_IMPLTSTART_CALLD & frame_pointer->type)
DBGTRIGR((stderr, "op_unwind: Unwinding frame 0x"lvaddr" with type %d which has SFF_IMPLTSTART_CALLD turned on\n",
@@ -118,9 +123,9 @@ void op_unwind(void)
zyerr_frame = NULL; /* If we have unwound past zyerr_frame, clear it */
if (frame_pointer)
{
- if ((frame_pointer < (stack_frame *)msp) || (frame_pointer > (stack_frame *)stackbase)
- || (frame_pointer < (stack_frame *)stacktop))
- rts_error(VARLSTCNT(1) ERR_STACKUNDERFLO);
+ if ((frame_pointer < (stack_frame *)msp)
+ || (frame_pointer > (stack_frame *)stackbase) || (frame_pointer < (stack_frame *)stacktop))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKUNDERFLO);
assert((frame_pointer < frame_pointer->old_frame_pointer) || (NULL == frame_pointer->old_frame_pointer));
}
/* We just unwound a frame. May have been either a zintrupt frame and/or may have unwound a NEW'd ZTRAP or even cleared
diff --git a/sr_port/op_view.c b/sr_port/op_view.c
index 70dbf0b..f6dc9c3 100644
--- a/sr_port/op_view.c
+++ b/sr_port/op_view.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -69,6 +69,9 @@
# include "gtmsecshr.h"
# endif
#endif
+#if defined(DEBUG) && defined(USHBIN_SUPPORTED)
+# include "relinkctl.h"
+#endif
#include "gtmimagename.h"
STATICFNDCL void view_dbflushop(unsigned char keycode, viewparm *parmblkptr, mval *thirdarg);
@@ -99,6 +102,8 @@ GBLREF boolean_t lvmon_enabled;
GBLREF spdesc stringpool;
GBLREF boolean_t is_updproc;
GBLREF pid_t process_id;
+GBLREF uint4 dollar_tlevel;
+UNIX_ONLY(GBLREF boolean_t dmterm_default;)
error_def(ERR_ACTRANGE);
error_def(ERR_COLLATIONUNDEF);
@@ -111,6 +116,7 @@ error_def(ERR_JNLFLUSH);
error_def(ERR_PATLOAD);
error_def(ERR_PATTABNOTFND);
error_def(ERR_REQDVIEWPARM);
+error_def(ERR_SEFCTNEEDSFULLB);
error_def(ERR_TEXT);
error_def(ERR_TRACEON);
error_def(ERR_VIEWCMD);
@@ -140,7 +146,7 @@ void op_view(UNIX_ONLY_COMMA(int numarg) mval *keyword, ...)
{
int4 testvalue, tmpzdefbufsiz;
uint4 jnl_status, dummy_errno;
- int status, lcnt, icnt;
+ int status, lcnt, icnt, recnum;
gd_region *reg, *r_top, *save_reg;
gv_namehead *gvnh;
mval *arg, *nextarg, outval;
@@ -167,6 +173,10 @@ void op_view(UNIX_ONLY_COMMA(int numarg) mval *keyword, ...)
symval *lvlsymtab;
lv_blk *lvbp;
lv_val *lvp, *lvp_top;
+# if defined(DEBUG) && defined(USHBIN_SUPPORTED)
+ open_relinkctl_sgm *linkctl;
+ relinkrec_t *linkrec;
+# endif
VMS_ONLY(int numarg;)
static readonly char msg1[] = "Caution: Database Block Certification Has Been ";
@@ -230,6 +240,14 @@ void op_view(UNIX_ONLY_COMMA(int numarg) mval *keyword, ...)
arg = (numarg > 1) ? va_arg(var, mval *) : NULL;
view_dbflushop(vtp->keycode, &parmblk, arg);
break;
+# ifdef UNIX
+ case VTK_DMTERM:
+ dmterm_default = TRUE;
+ break;
+ case VTK_NODMTERM:
+ dmterm_default = FALSE;
+ break;
+# endif
case VTK_FULLBOOL:
TREF(gtm_fullbool) = FULL_BOOL;
break;
@@ -237,7 +255,10 @@ void op_view(UNIX_ONLY_COMMA(int numarg) mval *keyword, ...)
TREF(gtm_fullbool) = FULL_BOOL_WARN;
break;
case VTK_NOFULLBOOL:
- TREF(gtm_fullbool) = GTM_BOOL;
+ if (OLD_SE == TREF(side_effect_handling))
+ TREF(gtm_fullbool) = GTM_BOOL;
+ else
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_SEFCTNEEDSFULLB);
break;
case VTK_GDSCERT0:
outval.mvtype = MV_STR;
@@ -329,9 +350,12 @@ void op_view(UNIX_ONLY_COMMA(int numarg) mval *keyword, ...)
# endif
case VTK_JNLWAIT:
/* go through all regions that could have possibly been open across all global directories */
- for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr))
- for (reg = addr_ptr->regions, r_top = reg + addr_ptr->n_regions; reg < r_top; reg++)
- jnl_wait(reg);
+ if (!dollar_tlevel)
+ { /* Only if we're not in a TP transaction */
+ for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr))
+ for (reg = addr_ptr->regions, r_top = reg + addr_ptr->n_regions; reg < r_top; reg++)
+ jnl_wait(reg);
+ }
break;
case VTK_JOBPID:
outval.mvtype = MV_STR;
@@ -781,6 +805,27 @@ void op_view(UNIX_ONLY_COMMA(int numarg) mval *keyword, ...)
op_wteol(1);
break;
# endif
+# if defined(DEBUG) && defined(USHBIN_SUPPORTED)
+ case VTK_RCTLDUMP:
+ util_out_print("", RESET); /* Reset output buffer */
+ for (linkctl = TREF(open_relinkctl_list); NULL != linkctl; linkctl = linkctl->next)
+ {
+ util_out_print_gtmio("relinkctl: 0x!XJ entryname: !AD records: !UL hdr: 0x!XJ base: 0x!XJ"
+ " locked: !UL", FLUSH, linkctl, linkctl->zro_entry_name.len,
+ linkctl->zro_entry_name.addr, linkctl->n_records, linkctl->hdr,
+ linkctl->rec_base, linkctl->locked);
+ util_out_print_gtmio(" hdr: records: !UL nattached: !UL", FLUSH, linkctl->hdr->n_records,
+ linkctl->hdr->nattached);
+ for (linkrec = linkctl->rec_base, recnum = 1; recnum <= linkctl->hdr->n_records;
+ linkrec++, recnum++)
+ {
+ util_out_print_gtmio(" rec#!4UL: rtnname: !AD cycle: !UL", FLUSH, recnum,
+ mid_len(&linkrec->rtnname_fixed), &linkrec->rtnname_fixed.c,
+ linkrec->cycle);
+ }
+ }
+ break;
+# endif
default:
va_end(var);
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_VIEWCMD);
@@ -848,7 +893,7 @@ void view_dbflushop(unsigned char keycode, viewparm *parmblkptr, mval *thirdarg)
* TPFAIL error because we are already in the final retry. By passing the WCSFLU_IN_COMMIT
* bit, we instruct wcs_flu to avoid wcs_recover.
*/
- wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH | WCSFLU_IN_COMMIT);
+ wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_IN_COMMIT | WCSFLU_SPEEDUP_NOBEFORE);
}
break;
case VTK_JNLFLUSH:
diff --git a/sr_port/op_xkill.c b/sr_port/op_xkill.c
index 1fd6dd4..c53bdfc 100644
--- a/sr_port/op_xkill.c
+++ b/sr_port/op_xkill.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,14 +12,20 @@
#include "mdef.h"
#include <stdarg.h>
-
+#include "gtm_stdio.h"
#include "gtm_string.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "op.h"
+#include "gdsroot.h"
+#include "gtm_facility.h"
+#include "fileinfo.h"
+#include "gdsbt.h"
+#include "gdsfhead.h"
+#include "alias.h"
GBLREF symval *curr_symval;
-GBLREF lv_val *active_lv;
GBLREF uint4 lvtaskcycle;
GBLREF boolean_t gtm_stdxkill;
@@ -34,8 +40,8 @@ void op_xkill(UNIX_ONLY_COMMA(int n) mval *lvname_arg, ...)
ht_ent_mname *tabent, *top;
boolean_t lcl_stdxkill;
- active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful. clear active_lv to avoid later
- cleanup problems */
+ SET_ACTIVE_LV(NULL, TRUE, actlv_op_xkill); /* If we get here, subscript set was successful.
+ * Clear active_lv to avoid later cleanup issues */
/* GTM supports two methods for exclusive kill that affect the way aliases and pass-by-reference (PBR) parameters are
* treated when used in an exclusive kill.
* - M Standard - An alias or PBR var specified in an xkill list while its aliases are NOT in the list is killed.
diff --git a/sr_port/op_xnew.c b/sr_port/op_xnew.c
index c8365a5..3271dd6 100644
--- a/sr_port/op_xnew.c
+++ b/sr_port/op_xnew.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,6 +16,7 @@
#include "gtm_string.h"
#include "gtm_stdio.h"
+#include "gtmio.h"
#include "lv_val.h"
#include "gdsroot.h"
#include "gtm_facility.h"
@@ -26,37 +27,46 @@
#include <rtnhdr.h>
#include "stack_frame.h"
#include "alias.h"
+#include "error.h"
-GBLREF lv_xnew_var *xnewvar_anchor;
GBLREF lv_xnew_ref *xnewref_anchor;
-GBLREF uint4 lvtaskcycle;
+GBLREF lv_xnew_var *xnewvar_anchor;
+GBLREF stack_frame *frame_pointer;
GBLREF symval *curr_symval;
+GBLREF uint4 lvtaskcycle;
GBLREF unsigned char *stackbase, *msp;
+STATICDEF stack_frame *fp_save;
+
+STATICFNDCL void guard_against_zbzst(void);
+
+CONDITION_HANDLER(zbreak_zstep_xnew_ch);
+
/* Exclusive new - Operation:
+ *
+ * 1) Push a new symtab onto the stack via mv_stent entry
+ * 2) For each var name listed that is not to be NEW'd:
+ * a) lookup the var in the old symbol table (create if does not exist)
+ * b) add the symbol to the new symbol table.
+ * c) copy the lv_val address from the old symbol table to the new symbol
+ * table.
+ * d) save the var name in a chain off of the symtab so we know which vars
+ * need special alias consideration processing when the symtab pops
+ * in umw_mv_stent().
+ */
- 1) Push a new symtab onto the stack via mv_stent entry
- 2) For each var name listed that is not to be NEW'd:
- a) lookup the var in the old symbol table (create if does not exist)
- b) add the symbol to the new symbol table.
- c) copy the lv_val address from the old symbol table to the new symbol
- table.
- d) save the var name in a chain off of the symtab so we know which vars
- need special alias consideration processing when the symtab pops
- in umw_mv_stent().
-*/
void op_xnew(UNIX_ONLY_COMMA(unsigned int argcnt_arg) mval *s_arg, ...)
{
- va_list var;
- unsigned int argcnt;
- mval *s;
- int4 shift;
- var_tabent lvent;
- ht_ent_mname *tabent1, *tabent2;
- hash_table_mname *htold, *htnew;
- lv_xnew_var *xnewvar;
- lv_val *lvp, *lvtab1;
- boolean_t added;
+ boolean_t added;
+ ht_ent_mname *tabent1, *tabent2;
+ hash_table_mname *htold, *htnew;
+ int argcnt;
+ int4 shift;
+ lv_val *lvp, *lvtab1;
+ lv_xnew_var *xnewvar;
+ mval *s;
+ va_list var;
+ var_tabent lvent;
VMS_ONLY(va_count(argcnt));
UNIX_ONLY(argcnt = argcnt_arg); /* need to preserve stack copy on i386 */
@@ -65,7 +75,11 @@ void op_xnew(UNIX_ONLY_COMMA(unsigned int argcnt_arg) mval *s_arg, ...)
DBGRFCT((stderr, "\n\n****op_xnew: **** New symbol table (0x"lvaddr") replaced previous table (0x"lvaddr")\n\n",
curr_symval, curr_symval->last_tab));
if (0 >= argcnt)
- return; /* done if no arguments */
+ {
+ if (shift)
+ guard_against_zbzst();
+ return;
+ }
INCR_LVTASKCYCLE; /* So we don't process referenced base vars more than once */
htnew = &curr_symval->h_symtab;
assert(curr_symval->last_tab);
@@ -91,7 +105,7 @@ void op_xnew(UNIX_ONLY_COMMA(unsigned int argcnt_arg) mval *s_arg, ...)
if (added)
{ /* This var has NOT been specified twice */
tabent2->value = tabent1->value;
- lvp = (lv_val *)tabent2->value;
+ lvp = (lv_val *)tabent2->value; /* Same lv_val pointed to by both hashtabs */
if (lvp && (IS_ALIASLV(lvp) || lvp->has_aliascont))
curr_symval->alias_activity = TRUE; /* Loading an alias into new symtab counts as
* activity! */
@@ -108,10 +122,10 @@ void op_xnew(UNIX_ONLY_COMMA(unsigned int argcnt_arg) mval *s_arg, ...)
INCR_CREFCNT(lvtab1);
INCR_TREFCNT(lvtab1);
/* Note that there is no attempt to prevent double processing an lvval that has been indicated
- through more than one (aliased) var being passed through. This is because these vars could be
- independent by the time they come back through when the symtab pops. So we will handle them the
- same way then.
- */
+ * through more than one (aliased) var being passed through. This is because these vars could be
+ * independent by the time they come back through when the symtab pops. So we will handle them the
+ * same way then.
+ */
lvtab1->stats.lvtaskcycle = lvtaskcycle;
} else
/* Apparently var was specified twice -- better have value set as we expect it */
@@ -123,15 +137,60 @@ void op_xnew(UNIX_ONLY_COMMA(unsigned int argcnt_arg) mval *s_arg, ...)
}
va_end(var);
/* Now that all the passed-thru vars have been identified and recorded, go through them again to process their arrays
- and search for containers pointing to other arrays that we need to record */
+ * and search for containers pointing to other arrays that we need to record.
+ */
if (curr_symval->alias_activity)
{
for (xnewvar = curr_symval->xnew_var_list; xnewvar; xnewvar = xnewvar->next)
{
lvtab1 = xnewvar->lvval;
- if (LV_HAS_CHILD(lvtab1))
- XNEWREF_CNTNRS_IN_TREE(lvtab1);
+ XNEWREF_CNTNRS_IN_TREE(lvtab1); /* note macro has LV_GET_CHILD exists check */
}
}
+ if (shift)
+ guard_against_zbzst();
return;
}
+
+CONDITION_HANDLER(zbreak_zstep_xnew_ch)
+{
+ START_CH(TRUE);
+ frame_pointer = fp_save;
+ NEXTCH;
+}
+
+STATICFNDEF void guard_against_zbzst(void)
+{ /* if the new symbol table slid into the stack, then we guard against ZBREAK and ZSTEP having taken us to the xnew
+ * this could be done sligthly more efficiently and with stronger asserts using custom code, but this is an edge case,
+ * so we use, with an empty argument list, gtm_fetch et al to do the job
+ */
+ boolean_t fetch;
+ stack_frame *fp, *fp_prev;
+
+ fp = frame_pointer;
+ assert(!(fp->type & SFT_COUNT));
+ fp_prev = fp->old_frame_pointer;
+ assert(fp_prev);
+ fetch = (fp->type & (SFT_ZBRK_ACT | SFT_ZSTEP_ACT));
+ while (!(fp_prev->type & SFT_COUNT))
+ { /* find where we put the new symbol table like we did in symbinit but with additional checking on frame types */
+ fp = fp_prev;
+ fetch |= (fp->type & (SFT_ZBRK_ACT | SFT_ZSTEP_ACT));
+ fp_prev = fp->old_frame_pointer;
+ assert(fp_prev);
+ }
+ if (fetch)
+ { /* only need to fetch if there is a zbreak or zstep frame in between our current position and the adjusted frame
+ * all other non SFT_COUNT frames either require a quit (SFT_ZINTR & SFT_TRIGR) which unstacks the symbol table
+ * protected by the NEW, or return to the beginning of the line (SFT_REP_OP & SFT_DEV_ACT & SFT_ZTRAP) which cause
+ * a refetch, or vector to a new virtual line (SFT_ZTRAP, but for $ZTRAP)
+ */
+ ESTABLISH(zbreak_zstep_xnew_ch);
+ fp_save = frame_pointer;
+ frame_pointer = fp_prev; /* pretend we're in the original frame */
+ UNIX_ONLY(gtm_fetch(0, 0)); /* refetch everything in the old table into the new one */
+ VMS_ONLY(fetch_all()); /* call an assembly interlude so VMS gets to gtm_fetch */
+ frame_pointer = fp_save; /* restore the proper frame_pointer */
+ REVERT;
+ }
+}
diff --git a/sr_port/op_zhalt.c b/sr_port/op_zhalt.c
index 465cef1..3269d51 100644
--- a/sr_port/op_zhalt.c
+++ b/sr_port/op_zhalt.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2011 Fidelity Information Services, Inc *
+ * Copyright 2011, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -44,12 +44,12 @@ void op_zhalt(mval *returncode)
/* If ZHALT is done from a non-runtime trigger, send a warning message to oplog to record the fact
* of this uncommon process termination method.
*/
- if (!IS_GTM_IMAGE && !IS_GTM_SVC_DAL_IMAGE)
+ if (!IS_GTM_IMAGE)
{
zposition.mvtype = 0; /* It's not an mval yet till getzposition fills it in */
getzposition(&zposition);
assert(MV_IS_STRING(&zposition) && (0 < zposition.str.len));
- send_msg(VARLSTCNT(9) ERR_PROCTERM, 7, GTMIMAGENAMETXT(image_type), RTS_ERROR_TEXT("ZHALT"),
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_PROCTERM, 7, GTMIMAGENAMETXT(image_type), RTS_ERROR_TEXT("ZHALT"),
retcode, zposition.str.len, zposition.str.addr);
}
# endif
diff --git a/sr_port/op_zprevious.c b/sr_port/op_zprevious.c
index c6179a4..d0d55a7 100644
--- a/sr_port/op_zprevious.c
+++ b/sr_port/op_zprevious.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -118,7 +118,8 @@ void op_zprevious(mval *v)
ENSURE_STP_FREE_SPACE(n);
}
v->str.addr = (char *)stringpool.free;
- stringpool.free = gvsub2str(&gv_altkey->base[gv_altkey->prev], stringpool.free, FALSE);
+ v->str.len = MAX_KEY_SZ;
+ stringpool.free = gvsub2str(&gv_altkey->base[gv_altkey->prev], &(v->str), FALSE);
v->str.len = INTCAST((char *)stringpool.free - v->str.addr);
assert(v->str.addr < (char *)stringpool.top && v->str.addr >= (char *)stringpool.base);
assert(v->str.addr + v->str.len <= (char *)stringpool.top &&
diff --git a/sr_port/op_zshow.c b/sr_port/op_zshow.c
index 57954f0..5a37177 100644
--- a/sr_port/op_zshow.c
+++ b/sr_port/op_zshow.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -27,11 +27,12 @@
#include "gtm_maxstr.h"
#include "svnames.h"
-GBLREF gv_key *gv_currkey;
+GBLREF lv_val *active_lv;
+GBLREF gv_key *gv_currkey;
error_def(ERR_ZSHOWBADFUNC);
-void op_zshow(mval *func,int type,lv_val *lvn)
+void op_zshow(mval *func, int type, lv_val *lvn)
{
const char *ptr;
boolean_t do_all = FALSE,
@@ -186,4 +187,9 @@ void op_zshow(mval *func,int type,lv_val *lvn)
output.flush = TRUE;
zshow_output(&output,0);
MAXSTR_BUFF_FINI;
+ /* If ZSHOW was done onto a subscripted lvn but no zshow records got dumped in that lvn, it might have $data = 0.
+ * Kill it in that case as otherwise it will create an out-of-design situation for $query(lvn).
+ */
+ if ((type == ZSHOW_LOCAL) && (active_lv == lvn))
+ UNDO_ACTIVE_LV(actlv_op_zshow);
}
diff --git a/sr_port/opcode_def.h b/sr_port/opcode_def.h
index f2aab23..c8ee247 100644
--- a/sr_port/opcode_def.h
+++ b/sr_port/opcode_def.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -342,3 +342,8 @@ OPCODE_DEF(OC_INDMERGE2, (OCT_NULL))
OPCODE_DEF(OC_LITC, (OCT_MVAL | OCT_EXPRLEAF))
OPCODE_DEF(OC_STOLITC, (OCT_NULL))
OPCODE_DEF(OC_FNZPEEK, (OCT_MVAL | OCT_EXPRLEAF))
+OPCODE_DEF(OC_FNZSOCKET, (OCT_MVAL | OCT_EXPRLEAF))
+OPCODE_DEF(OC_FNZSYSLOG, (OCT_MVAL | OCT_EXPRLEAF))
+OPCODE_DEF(OC_RHD_EXT, (OCT_CDADDR))
+OPCODE_DEF(OC_LAB_EXT, (OCT_CDADDR))
+OPCODE_DEF(OC_ZRUPDATE, (OCT_NULL))
diff --git a/sr_port/outofband.h b/sr_port/outofband.h
index 30779b9..b36fbe6 100644
--- a/sr_port/outofband.h
+++ b/sr_port/outofband.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -31,12 +31,7 @@ enum outofbands
#define OUTOFBAND_RESTARTABLE(event) (jobinterrupt == (event))
-/* ------------------------------------------------------------------
- * Old-style declarations (and uses) of this function abound.
- * Be sure to change all declarations at once!
- * ------------------------------------------------------------------
- */
-void outofband_action(bool);
+void outofband_action(boolean_t line_fetch_or_start);
void outofband_clear(void);
diff --git a/sr_port/outofband_action.c b/sr_port/outofband_action.c
index fd4d505..2921170 100644
--- a/sr_port/outofband_action.c
+++ b/sr_port/outofband_action.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2007 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -17,21 +17,19 @@
#include "stack_frame.h"
#include "outofband.h"
-GBLREF volatile int4 outofband;
-GBLREF volatile int4 ctrap_action_is;
GBLREF io_pair io_std_device;
GBLREF stack_frame *frame_pointer;
-GBLREF unsigned char *restart_pc;
-GBLREF unsigned char *restart_ctxt;
+GBLREF unsigned char *restart_ctxt, *restart_pc;
GBLREF void (*tp_timeout_action_ptr)(void);
+GBLREF volatile int4 ctrap_action_is, outofband;
-void outofband_action(bool lnfetch_or_start)
-{
- error_def(ERR_CTRAP);
- error_def(ERR_CTRLC);
- error_def(ERR_CTRLY);
- error_def(ERR_JOBINTRRQST);
+error_def(ERR_CTRAP);
+error_def(ERR_CTRLC);
+error_def(ERR_CTRLY);
+error_def(ERR_JOBINTRRQST);
+void outofband_action(boolean_t lnfetch_or_start)
+{
if (outofband)
{
if (io_std_device.in->type == tt)
@@ -41,17 +39,16 @@ void outofband_action(bool lnfetch_or_start)
restart_pc = frame_pointer->mpc;
restart_ctxt = frame_pointer->ctxt;
}
-
switch(outofband)
{
case (ctrly):
- rts_error(VARLSTCNT(1) ERR_CTRLY);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLY);
break;
case (ctrlc):
- rts_error(VARLSTCNT(1) ERR_CTRLC);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
break;
case (ctrap):
- rts_error(VARLSTCNT(3) ERR_CTRAP, 1, ctrap_action_is);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_CTRAP, 1, ctrap_action_is);
break;
case (tptimeout):
/*
@@ -61,10 +58,10 @@ void outofband_action(bool lnfetch_or_start)
(*tp_timeout_action_ptr)();
break;
case (jobinterrupt):
- rts_error(VARLSTCNT(1) ERR_JOBINTRRQST);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_JOBINTRRQST);
break;
default:
- GTMASSERT;
+ assertpro(FALSE);
break;
}
}
diff --git a/sr_port/patstr.c b/sr_port/patstr.c
index 24689c5..bd674b1 100644
--- a/sr_port/patstr.c
+++ b/sr_port/patstr.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -29,6 +29,7 @@ GBLREF boolean_t gtm_utf8_mode;
LITREF char ctypetab[NUM_CHARS];
LITREF uint4 typemask[PATENTS];
+error_def(ERR_COMMAORRPAREXP);
error_def(ERR_PATCLASS);
error_def(ERR_PATCODE);
error_def(ERR_PATLIT);
@@ -162,7 +163,11 @@ int patstr(mstr *instr, ptstr *obj, unsigned char **relay)
prev_fixed_len = fixed_len;
if ((NULL != relay) && !saw_delimiter)
{
- assert(!topseen);
+ if (topseen)
+ {
+ instr->addr = (char *)(in_top + 1);
+ return ERR_COMMAORRPAREXP;
+ }
if ((',' == curchar) || (')' == curchar))
{
*relay = (inchar - 1);
@@ -512,6 +517,11 @@ int patstr(mstr *instr, ptstr *obj, unsigned char **relay)
} while (TRUE);
if (0 == pattern_mask)
{
+ if (any_alt)
+ {
+ instr->addr = alttail.addr + 1;
+ return ERR_PATCODE;
+ }
instr->addr = topseen ? (char *)inchar + 1 : (char *)inchar;
return ERR_PATCLASS;
}
diff --git a/sr_port/print_target.c b/sr_port/print_target.c
index ed5d7fc..d9cab0f 100644
--- a/sr_port/print_target.c
+++ b/sr_port/print_target.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,6 +33,7 @@ void print_target(unsigned char *c)
uint4 ch;
boolean_t bad_sub = FALSE;
boolean_t is_string;
+ mstr opstr;
ptop = c + MAX_KEY_SZ;
for (p = buff, ptr = c; *ptr && (ptr < ptop); ptr++)
@@ -77,7 +78,9 @@ void print_target(unsigned char *c)
break;
}
}
- top = gvsub2str(ptr, buff, FALSE);
+ opstr.addr = (char *)buff;
+ opstr.len = MAX_ZWR_KEY_SZ + SIZEOF("?.0");
+ top = gvsub2str(ptr, &opstr, FALSE);
if (!is_string && (0x80 != *ptr++) && (KEY_DELIMITER == *ptr))
{
top = (unsigned char *)(buff + SIZEOF("?.0")); /* to allow a bit of garbage, in case it's helpful */
diff --git a/sr_port/randstr.mpt b/sr_port/randstr.mpt
index e7c7443..8321dd6 100644
--- a/sr_port/randstr.mpt
+++ b/sr_port/randstr.mpt
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2011 Fidelity Information Services, Inc ;
+; Copyright 2011, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -34,8 +34,8 @@
. set patcodes="1."_$select($length($get(patcodes)):$translate(patcodes,$translate(patcodes,a)),1:"AN")
. for i=1:1:$length(x) set y=$extract(x,i) set:y?@patcodes charset=$get(charset)_y
. quit
- set n=$length(charset) ; n has number of characters in alphabet
- for i=1:1:$select($length($get(strlen)):strlen,1:8) set z=$get(z)_$extract(charset,$random(n)+1) ; generate random string
+ set n=$length(charset),z="" ; n has number of characters in alphabet; z is result
+ for i=1:1:$select($length($get(strlen)):strlen,1:8) set z=z_$extract(charset,$random(n)+1) ; generate random string
quit:$quit z ; extrinsic
write z
quit
diff --git a/sr_port/release_private_code_copy.c b/sr_port/release_private_code_copy.c
index 4cf6434..7893e6f 100644
--- a/sr_port/release_private_code_copy.c
+++ b/sr_port/release_private_code_copy.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2002, 2007 Fidelity Information Services, Inc *
+ * Copyright 2002, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,15 +19,20 @@ void adjust_frames(unsigned char *old_ptext_beg, unsigned char *old_ptext_end, u
void release_private_code_copy(rhdtyp *rtn)
{
-#ifdef USHBIN_SUPPORTED
- assert(NULL != rtn->shlib_handle);
- assert(NULL != rtn->shared_ptext_adr);
+# ifdef USHBIN_SUPPORTED
+ assert(NULL != rtn->shared_ptext_adr);
+ assert(rtn->shared_ptext_adr != rtn->ptext_adr);
- adjust_frames(rtn->ptext_adr, rtn->ptext_end_adr, rtn->shared_ptext_adr);
- GTM_TEXT_FREE(rtn->ptext_adr);
+ adjust_frames(rtn->ptext_adr, rtn->ptext_end_adr, rtn->shared_ptext_adr);
+ GTM_TEXT_FREE(rtn->ptext_adr);
+ do
+ { /* Since more than one version of a module may exist at a given time, run the routine
+ * header chain and check all versions - releasing the private copy if it exists.
+ */
rtn->ptext_end_adr = rtn->shared_ptext_adr + (rtn->ptext_end_adr - rtn->ptext_adr);
rtn->ptext_adr = rtn->shared_ptext_adr;
- rtn->shared_ptext_adr = NULL;
-#endif
+ rtn = (rhdtyp *)rtn->old_rhead_adr;
+ } while (NULL != rtn);
+# endif
return;
}
diff --git a/sr_port/repl_comm.h b/sr_port/repl_comm.h
index 312a964..f35f38b 100644
--- a/sr_port/repl_comm.h
+++ b/sr_port/repl_comm.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -69,7 +69,7 @@ for (msg_ptr = (unsigned char *)(BUFF), recvd_len = 0, recvd_this_iter = torecv_
#define VMS_MAX_TCP_SEND_SIZE VMS_MAX_TCP_IO_SIZE
#define VMS_MAX_TCP_RECV_SIZE VMS_MAX_TCP_IO_SIZE
-#define GTMSOURCE_IDLE_POLL_WAIT 100 /* 100ms sleep in case nothing sent to the other side */
+#define GTMSOURCE_IDLE_POLL_WAIT 1 /* 1ms sleep in case nothing sent to the other side */
#define REPL_POLL_WAIT (MILLISECS_IN_SEC - 1) /* Maximum time (in ms) for select()/poll() to timeout */
#define REPL_POLL_NOWAIT 0 /* Forces poll()/select() to return immediately */
#define REPL_INVALID_POLL_DIRECTION -1
diff --git a/sr_port/repl_ctl.h b/sr_port/repl_ctl.h
index aa2439b..fd9aed9 100644
--- a/sr_port/repl_ctl.h
+++ b/sr_port/repl_ctl.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -93,7 +93,14 @@ typedef struct repl_ctl_struct
seq_num min_seqno; /* least JNL_SEQNO in this file */
seq_num max_seqno; /* largest JNL_SEQNO in this file */
uint4 min_seqno_dskaddr;
- uint4 max_seqno_dskaddr;
+ uint4 max_seqno_dskaddr; /* offset in jnl file where max_seqno was found */
+# ifdef UNIX
+ uint4 max_seqno_eof_addr; /* eof_addr of jnl file WHEN max_seqno/max_seqno_dskaddr was found.
+ * Used in "update_max_seqno_info" to ascertain if nothing changed
+ * since the last call to this function and if so return right away
+ */
+ uint4 filler_4byte;
+# endif
seq_num seqno; /* Next read positioned at first
* jnl rec with JNL_SEQNO seqno */
trans_num tn; /* tn corresponding to seqno */
diff --git a/sr_port/repl_dbg.h b/sr_port/repl_dbg.h
index dc55c29..699b9d1 100644
--- a/sr_port/repl_dbg.h
+++ b/sr_port/repl_dbg.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,6 +13,7 @@
#define REPL_DBG_H
#ifdef REPL_DEBUG
+#include "gtmio.h"
#include "gtm_stdio.h"
#define REPL_DEBUG_ONLY(stmt) stmt
diff --git a/sr_port/repl_filter.c b/sr_port/repl_filter.c
index 34ab1cd..6a9d933 100644
--- a/sr_port/repl_filter.c
+++ b/sr_port/repl_filter.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -57,8 +57,11 @@
#include "gv_trigger_common.h" /* for HASHT* macros */
#include "replgbl.h"
#ifdef UNIX
-#include "heartbeat_timer.h"
#include "gtm_c_stack_trace.h"
+#include "fork_init.h"
+#endif
+#ifdef DEBUG
+#include "wbox_test_init.h"
#endif
#ifdef GTM_USE_POLL_FOR_SUBSECOND_SELECT
#include <sys/poll.h>
@@ -165,7 +168,7 @@
#define DBG_CHECK_IF_CONVBUFF_VALID(CONV_BUFF, CONV_BUFFLEN)
#endif
-#define INITIALIZE_V22_UPDATE_NUM_FROM_V17(cstart, cb, jstart, jb, tset_num, update_num, rectype) \
+#define INITIALIZE_V24_UPDATE_NUM_FROM_V17(cstart, cb, jstart, jb, tset_num, update_num, rectype) \
{ \
assert((0 != tset_num) || (0 == update_num)); \
if (IS_TP(rectype)) \
@@ -180,7 +183,7 @@
cb += SIZEOF(uint4); \
}
-#define INITIALIZE_V22_MUMPS_NODE_FROM_V17(cstart, cb, jstart, jb, tail_minus_suffix_len, from_v15) \
+#define INITIALIZE_V24_MUMPS_NODE_FROM_V17(cstart, cb, jstart, jb, tail_minus_suffix_len, from_v15) \
{ \
uint4 nodelen; \
\
@@ -204,7 +207,7 @@
cb += tail_minus_suffix_len; \
}
-#define INITIALIZE_V22_TCOM_FROM_V17(cstart, cb, jstart, jb, tcom_num, tset_num, update_num) \
+#define INITIALIZE_V24_TCOM_FROM_V17(cstart, cb, jstart, jb, tcom_num, tset_num, update_num) \
{ \
uint4 num_participants; \
char tmp_jnl_tid[TID_STR_SIZE]; \
@@ -240,7 +243,7 @@
} \
}
-#define INITIALIZE_V17_MUMPS_NODE_FROM_V22(cstart, cb, jstart, jb, trigupd_type, to_v15) \
+#define INITIALIZE_V17_MUMPS_NODE_FROM_V24(cstart, cb, jstart, jb, trigupd_type, to_v15) \
{ \
uint4 tail_minus_suffix_len; \
unsigned char *ptr; \
@@ -264,7 +267,7 @@
/* Initialize "mumps_node" member */ \
memcpy(cb, jb, tail_minus_suffix_len); \
/* Check if bits 24-31 of "length" member (nodeflags field) of "mumps_node" field are \
- * set to a non-zero value. If so they need to be cleared as they are v22 format specific. \
+ * set to a non-zero value. If so they need to be cleared as they are v24 format specific. \
* Instead of checking, clear it unconditionally. \
*/ \
((jnl_string *)cb)->nodeflags = 0; \
@@ -274,7 +277,7 @@
cb += tail_minus_suffix_len; \
}
-#define INITIALIZE_V17_TCOM_FROM_V22(cstart, cb, jstart, jb) \
+#define INITIALIZE_V17_TCOM_FROM_V24(cstart, cb, jstart, jb) \
{ \
uint4 num_participants; \
\
@@ -286,7 +289,7 @@
jb += SIZEOF(unsigned short); \
assert((jb - jstart) == OFFSETOF(struct_jrec_tcom, num_participants)); \
assert(SIZEOF(unsigned short) == SIZEOF(((struct_jrec_tcom *)NULL)->num_participants)); \
- /* Take a copy of the num_participants field from V22's TCOM record */ \
+ /* Take a copy of the num_participants field from V24's TCOM record */ \
num_participants = *((unsigned short *)jb); \
jb += SIZEOF(unsigned short); \
/* Initialize "jnl_tid" member */ \
@@ -299,8 +302,8 @@
cb += SIZEOF(uint4); \
}
-/* Initialize a V22 format jrec_suffix structure in the conversion buffer */
-#define INITIALIZE_V22_JREC_SUFFIX(cstart, cb, jstart, jb, conv_reclen) \
+/* Initialize a V24 format jrec_suffix structure in the conversion buffer */
+#define INITIALIZE_V24_JREC_SUFFIX(cstart, cb, jstart, jb, conv_reclen) \
{ \
jrec_suffix *suffix_ptr; \
\
@@ -312,11 +315,11 @@
}
/* Initialize a V17 format jrec_suffix structure in the conversion buffer.
- * Since V17 and V22 have the same jrec_suffix structure, this uses the same macro.
+ * Since V17 and V24 have the same jrec_suffix structure, this uses the same macro.
*/
#define INITIALIZE_V17_JREC_SUFFIX(cstart, cb, jstart, jb, conv_reclen) \
{ \
- INITIALIZE_V22_JREC_SUFFIX(cstart, cb, jstart, jb, conv_reclen) \
+ INITIALIZE_V24_JREC_SUFFIX(cstart, cb, jstart, jb, conv_reclen) \
}
#define INITIALIZE_V17_NULL_RECORD(PREFIX, CB, SEQNO) \
@@ -341,12 +344,12 @@
CB += JREC_SUFFIX_SIZE; \
}
-#define INITIALIZE_V22_NULL_RECORD(PREFIX, CB, SEQNO, STRM_SEQNO) \
+#define INITIALIZE_V24_NULL_RECORD(PREFIX, CB, SEQNO, STRM_SEQNO) \
{ \
jrec_suffix *suffix; \
\
(PREFIX)->jrec_type = JRT_NULL; \
- (PREFIX)->forwptr = V22_NULL_RECLEN; \
+ (PREFIX)->forwptr = V24_NULL_RECLEN; \
/* pini_addr, time, checksum and tn fields of "jrec_prefix" are not \
* used by update process so dont bother initializing them. \
*/ \
@@ -364,7 +367,7 @@
CB += SIZEOF(uint4); \
/* Initialize the suffix */ \
suffix = (jrec_suffix *)(CB); \
- suffix->backptr = V22_NULL_RECLEN; \
+ suffix->backptr = V24_NULL_RECLEN; \
suffix->suffix_code = JNL_REC_SUFFIX_CODE; \
CB += JREC_SUFFIX_SIZE; \
}
@@ -403,29 +406,28 @@ enum
NON_REPLIC_JREC_TRIG /* This update was done inside of a trigger */
};
-/* Although V6.0-000 bumped up the journal format version from V22 to V23, there are no changes between the
- * two's journal format structures. The reason for increasing the journal version
- */
GBLDEF intlfltr_t repl_filter_cur2old[JNL_VER_THIS - JNL_VER_EARLIEST_REPL + 1] =
{
- IF_22TO17, /* Convert from filter format V22 to V17 (i.e., from jnl ver V23 to V17) */
- IF_22TO17, /* Convert from filter format V22 to V17 (i.e., from jnl ver V23 to V18) */
- IF_22TO19, /* Convert from filter format V22 to V19 (i.e., from jnl ver V23 to V19) */
- IF_22TO19, /* Convert from filter format V22 to V19 (i.e., from jnl ver V23 to V20) */
- IF_22TO21, /* Convert from filter format V22 to V21 (i.e., from jnl ver V23 to V21) */
- IF_22TO22, /* Convert from filter format V22 to V22 (i.e., from jnl ver V23 to V22) */
- IF_22TO22 /* Convert from filter format V22 to V22 (i.e., from jnl ver V23 to V23) */
+ IF_24TO17, /* Convert from filter format V24 to V17 (i.e., from jnl ver V24 to V17) */
+ IF_24TO17, /* Convert from filter format V24 to V17 (i.e., from jnl ver V24 to V18) */
+ IF_24TO19, /* Convert from filter format V24 to V19 (i.e., from jnl ver V24 to V19) */
+ IF_24TO19, /* Convert from filter format V24 to V19 (i.e., from jnl ver V24 to V20) */
+ IF_24TO21, /* Convert from filter format V24 to V21 (i.e., from jnl ver V24 to V21) */
+ IF_24TO22, /* Convert from filter format V24 to V22 (i.e., from jnl ver V24 to V22) */
+ IF_24TO22, /* Convert from filter format V24 to V22 (i.e., from jnl ver V24 to V23) */
+ IF_24TO24 /* Convert from filter format V24 to V24 (i.e., from jnl ver V24 to V24) */
};
GBLDEF intlfltr_t repl_filter_old2cur[JNL_VER_THIS - JNL_VER_EARLIEST_REPL + 1] =
{
- IF_17TO22, /* Convert from filter format V17 to V22 (i.e., from jnl ver V17 to V23) */
- IF_17TO22, /* Convert from filter format V17 to V22 (i.e., from jnl ver V18 to V23) */
- IF_19TO22, /* Convert from filter format V19 to V22 (i.e., from jnl ver V19 to V23) */
- IF_19TO22, /* Convert from filter format V19 to V22 (i.e., from jnl ver V20 to V23) */
- IF_21TO22, /* Convert from filter format V21 to V22 (i.e., from jnl ver V21 to V23) */
- IF_22TO22, /* Convert from filter format V22 to V22 (i.e., from jnl ver V22 to V23) */
- IF_22TO22 /* Convert from filter format V22 to V22 (i.e., from jnl ver V23 to V23) */
+ IF_17TO24, /* Convert from filter format V17 to V24 (i.e., from jnl ver V17 to V24) */
+ IF_17TO24, /* Convert from filter format V17 to V24 (i.e., from jnl ver V18 to V24) */
+ IF_19TO24, /* Convert from filter format V19 to V24 (i.e., from jnl ver V19 to V24) */
+ IF_19TO24, /* Convert from filter format V19 to V24 (i.e., from jnl ver V20 to V24) */
+ IF_21TO24, /* Convert from filter format V21 to V24 (i.e., from jnl ver V21 to V24) */
+ IF_22TO24, /* Convert from filter format V22 to V24 (i.e., from jnl ver V22 to V24) */
+ IF_22TO24, /* Convert from filter format V22 to V24 (i.e., from jnl ver V23 to V24) */
+ IF_24TO24 /* Convert from filter format V24 to V24 (i.e., from jnl ver V24 to V24) */
};
GBLREF unsigned int jnl_source_datalen, jnl_dest_maxdatalen;
@@ -439,6 +441,9 @@ GBLREF boolean_t is_src_server, is_rcvr_server;
#ifdef UNIX
GBLREF repl_conn_info_t *this_side, *remote_side;
GBLREF volatile uint4 heartbeat_counter;
+#ifdef DEBUG
+GBLREF boolean_t heartbeat_started;
+#endif
#endif
GBLREF uint4 process_id;
@@ -455,8 +460,11 @@ static pid_t repl_filter_pid = -1;
static int repl_srv_filter_fd[2] = {FD_INVALID, FD_INVALID};
static int repl_filter_srv_fd[2] = {FD_INVALID, FD_INVALID};
static char *extract_buff;
+static int extract_bufsiz;
static char *recv_extract_buff;
+static int recv_extract_bufsiz;
static char *extr_rec;
+static int extr_bufsiz;
static char *srv_buff_start, *srv_buff_end, *srv_line_start, *srv_line_end, *srv_read_end;
static int recv_state;
@@ -547,7 +555,9 @@ int repl_filter_init(char *filter_cmd)
REPL_DPRINT2("Filter argc %d\n", index);
}
)
- if (0 < (repl_filter_pid = UNIX_ONLY(fork)VMS_ONLY(vfork)())) /* BYPASSOK: we exec immediately, no FORK_CLEAN needed */
+ UNIX_ONLY(FORK(repl_filter_pid);)
+ VMS_ONLY(repl_filter_pid = vfork();)
+ if (0 < repl_filter_pid)
{ /* Server */
UNIX_ONLY(
F_CLOSE(repl_srv_filter_fd[READ_END], close_res); /* SERVER: WRITE only on server -> filter pipe;
@@ -555,18 +565,41 @@ int repl_filter_init(char *filter_cmd)
F_CLOSE(repl_filter_srv_fd[WRITE_END], close_res); /* SERVER: READ only on filter -> server pipe;
* also resets "repl_srv_filter_fd[WRITE_END]" to FD_INVALID */
)
+ /* Make sure the write-end of the pipe is set to non-blocking. This will make sure repl_filter_send gets a
+ * EAGAIN error in case the write side of the pipe is full and waiting for the filter process to read it.
+ * In that case, we need to switch to reading to see if the filter process has sent any data to process.
+ * Not setting to O_NONBLOCK will cause us (server) to effectively deadlock (since we will wait indefinitely
+ * for the write to succeed but the pipe is full and the filter process cannot clear the pipe (i.e. read data
+ * from the pipe) until we read data that it has already written to its write end of the pipe.
+ */
+ FCNTL3(repl_srv_filter_fd[WRITE_END], F_SETFL, O_NONBLOCK, fcntl_res);
+ if (0 > fcntl_res)
+ {
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_REPLFILTER, 0, ERR_TEXT, 2,
+ RTS_ERROR_LITERAL("fcntl : could not set non-blocking mode in write side of pipe"), ERRNO);
+ repl_errno = EREPL_FILTERSTART_FORK;
+ return(FILTERSTART_ERR);
+ }
memset((char *)&null_jnlrec, 0, NULL_RECLEN);
null_jnlrec.prefix.jrec_type = JRT_NULL;
null_jnlrec.suffix.suffix_code = JNL_REC_SUFFIX_CODE;
null_jnlrec.prefix.forwptr = null_jnlrec.suffix.backptr = NULL_RECLEN;
assert(NULL == extr_rec);
jnl_extr_init();
- extr_rec = malloc(ZWR_EXP_RATIO(MAX_LOGI_JNL_REC_SIZE) + 1); /* +1 to accommodate terminating null */
- assert(MAX_EXTRACT_BUFSIZ > ZWR_EXP_RATIO(MAX_LOGI_JNL_REC_SIZE));
- extract_buff = malloc(MAX_EXTRACT_BUFSIZ + 1); /* +1 to accommodate terminating null */
- recv_extract_buff = malloc(MAX_EXTRACT_BUFSIZ + 1); /* +1 to accommodate terminating null */
- srv_line_start = srv_line_end = srv_read_end = srv_buff_start = malloc(MAX_EXTRACT_BUFSIZ + 1);
- srv_buff_end = srv_buff_start + MAX_EXTRACT_BUFSIZ + 1;
+ extr_bufsiz = (ZWR_EXP_RATIO(MAX_LOGI_JNL_REC_SIZE) + 1); /* +1 to accommodate terminating null */
+ extr_rec = malloc(extr_bufsiz);
+ assert(MAX_ONE_JREC_EXTRACT_BUFSIZ > ZWR_EXP_RATIO(MAX_LOGI_JNL_REC_SIZE));
+ /* extract_buff and recv_extract_buff holds N journal records in extract format. So they might need
+ * N * MAX_ONE_JREC_EXTRACT_BUFSIZ space at the most. Start with 2*MAX_ONE_JREC_EXTRACT_BUFSIZ and
+ * expand as needed. Ensure while appending one extract line to this buffer, we always have at least
+ * MAX_ONE_JREC_EXTRACT_BUFSIZ space left.
+ */
+ extract_bufsiz = (2 * MAX_ONE_JREC_EXTRACT_BUFSIZ);
+ extract_buff = malloc(extract_bufsiz);
+ recv_extract_bufsiz = (2 * MAX_ONE_JREC_EXTRACT_BUFSIZ);
+ recv_extract_buff = malloc(recv_extract_bufsiz);
+ srv_line_start = srv_line_end = srv_read_end = srv_buff_start = malloc(MAX_ONE_JREC_EXTRACT_BUFSIZ);
+ srv_buff_end = srv_buff_start + MAX_ONE_JREC_EXTRACT_BUFSIZ;
return(SS_NORMAL);
}
if (0 == repl_filter_pid)
@@ -614,9 +647,9 @@ static int repl_filter_send(seq_num tr_num, unsigned char *tr, int tr_len, boole
{
/* Send the transaction tr_num in buffer tr of len tr_len to the filter */
ssize_t extr_len, sent_len;
- static ssize_t send_len;
+ static ssize_t send_len, prev_sent_len;
char first_rectype, *extr_end;
- static char *send_ptr;
+ char *send_ptr;
if (TRUE == first_send)
{
@@ -627,9 +660,10 @@ static int repl_filter_send(seq_num tr_num, unsigned char *tr, int tr_len, boole
is_null = (JRT_NULL == first_rectype);
save_jnl_seqno = GET_JNL_SEQNO(tr);
save_strm_seqno = GET_STRM_SEQNO(tr);
- extr_end = jnl2extcvt((jnl_record *)tr, tr_len, extract_buff);
+ extr_end = jnl2extcvt((jnl_record *)tr, tr_len, &extract_buff, &extract_bufsiz);
assertpro(NULL != extr_end);
extr_len = extr_end - extract_buff;
+ assert(extr_len < extract_bufsiz);
extract_buff[extr_len] = '\0';
} else
{
@@ -649,23 +683,30 @@ static int repl_filter_send(seq_num tr_num, unsigned char *tr, int tr_len, boole
);
send_ptr = extract_buff;
send_len = extr_len;
- }
- while (0 > (sent_len = write(repl_srv_filter_fd[WRITE_END], send_ptr, send_len)) &&
- (errno == EINTR ));
+ prev_sent_len = 0;
+ } else
+ send_ptr = extract_buff + prev_sent_len;
+ while (0 > (sent_len = write(repl_srv_filter_fd[WRITE_END], send_ptr, send_len))
+ && (errno == EINTR ))
+ ;
if (0 > sent_len)
{
+ if (EAGAIN == errno)
+ { /* write would block, so check for read side of pipe */
+ return MORE_TO_TRANSFER;
+ }
repl_errno = (EPIPE == errno) ? EREPL_FILTERNOTALIVE : EREPL_FILTERSEND;
return (ERRNO);
}
/* partial write if we get here, so let's go back and try recv */
- send_ptr += sent_len;
+ prev_sent_len += sent_len;
send_len -= sent_len;
if (send_len)
return(MORE_TO_TRANSFER);
return(SS_NORMAL);
}
-static int repl_filter_recv_line(char *line, int *line_len, int max_line_len, boolean_t send_done)
+STATICFNDEF int repl_filter_recv_line(char *line, int *line_len, int max_line_len, boolean_t send_done)
{ /* buffer input read from repl_filter_srv_fd[READ_END], return one line at a time; line separator is '\n' */
int save_errno, orig_heartbeat;
@@ -683,27 +724,26 @@ static int repl_filter_recv_line(char *line, int *line_len, int max_line_len, bo
for (; ;)
{
- for (; srv_line_end < srv_read_end && '\n' != *srv_line_end; srv_line_end++)
+ for ( ; (srv_line_end < srv_read_end) && ('\n' != *srv_line_end); srv_line_end++)
;
if (srv_line_end < srv_read_end) /* newline found */
{
l_len = (ssize_t)(srv_line_end - srv_line_start + 1); /* include '\n' in length */
+ assertpro((int)l_len <= max_line_len); /* allocated buffer should have been enough for ONE jnlrec */
+ memcpy(line, srv_line_start, l_len);
*line_len = (int4)l_len ;
- if ((int)l_len <= max_line_len)
+ srv_line_start = ++srv_line_end; /* move past '\n' for next line */
+ assert(srv_line_end <= srv_read_end);
+ REPL_EXTRA_DPRINT3("repl_filter: newline found, srv_line_end: 0x%x srv_read_end: 0x%x\n",
+ srv_line_end, srv_read_end);
+ exttype = (muextract_type)MUEXTRACT_TYPE(line);
+ /* First 2 bytes must be in valid journal extract format */
+ if ((0 > exttype) || (MUEXT_MAX_TYPES <= exttype))
{
- memcpy(line, srv_line_start, l_len);
- srv_line_start = ++srv_line_end; /* move past '\n' for next line */
- assert(srv_line_end <= srv_read_end);
- REPL_EXTRA_DPRINT3("repl_filter: newline found, srv_line_end: 0x%x srv_read_end: 0x%x\n",
- srv_line_end, srv_read_end);
- exttype = (muextract_type)MUEXTRACT_TYPE(line);
- /* First 2 bytes must be in valid journal extract format */
- if ((0 > exttype) || (MUEXT_MAX_TYPES <= exttype))
- return (repl_errno = EREPL_FILTERBADCONV);
- else
- return SS_NORMAL;
- }
- return (repl_errno = EREPL_FILTERNOSPC);
+ assert(WBTEST_EXTFILTER_INDUCE_ERROR == gtm_white_box_test_case_number);
+ return (repl_errno = EREPL_FILTERBADCONV);
+ } else
+ return SS_NORMAL;
}
/* newline not found, may have to read more data */
assert(srv_line_end == srv_read_end);
@@ -814,6 +854,7 @@ static int repl_filter_recv_line(char *line, int *line_len, int max_line_len, bo
repl_errno = EREPL_FILTERRECV;
return save_errno;
}
+ assert(FALSE);
/* srv_read_end == srv_buff_end => buffer is full but no new-line; since we allocated enough buffer for the largest
* possible logical record, this should be a bad conversion from the filter
*/
@@ -821,12 +862,12 @@ static int repl_filter_recv_line(char *line, int *line_len, int max_line_len, bo
}
}
-static int repl_filter_recv(seq_num tr_num, unsigned char *tr, int *tr_len, boolean_t send_done)
+STATICFNDEF int repl_filter_recv(seq_num tr_num, unsigned char **tr, int *tr_len, int *tr_bufsize, boolean_t send_done)
{ /* Receive the transaction tr_num into buffer tr. Return the length of the transaction received in tr_len */
static int firstrec_len, tcom_len, rec_cnt, extr_len, extr_reclen, unwrap_nontp;
int save_errno, status;
- char *extr_ptr, *tr_end;
- char *tcom_ptr;
+ char *extr_ptr, *tmp;
+ unsigned char *tr_end, *tcom_ptr;
assert(NULL != extr_rec);
@@ -835,17 +876,13 @@ static int repl_filter_recv(seq_num tr_num, unsigned char *tr, int *tr_len, bool
if (FIRST_RECV_COMPLETE > recv_state)
{
unwrap_nontp = FALSE; /* If this is TRUE then the filter program made a non-tp a transaction */
- if (SS_NORMAL != (status = repl_filter_recv_line(extr_rec, &firstrec_len, ZWR_EXP_RATIO(MAX_LOGI_JNL_REC_SIZE),
- send_done)))
- {
- assertpro(EREPL_FILTERNOSPC != repl_errno); /* why didn't we pre-allocate enough memory? */
+ if (SS_NORMAL != (status = repl_filter_recv_line(extr_rec, &firstrec_len, extr_bufsiz, send_done)))
return status;
- }
/* if send not done make sure we do a select before reading any more */
if (FALSE == send_done)
select_valid = FALSE;
-
- memcpy(recv_extract_buff, extr_rec, firstrec_len + 1); /* include terminating null */
+ assert(recv_extract_bufsiz > firstrec_len); /* assert initial allocation will always fit ONE extract line */
+ memcpy(recv_extract_buff, extr_rec, firstrec_len); /* note: includes terminating null */
extr_reclen = extr_len = firstrec_len;
rec_cnt = 0;
REPL_DEBUG_ONLY(extr_rec[extr_reclen] = '\0';)
@@ -862,27 +899,32 @@ static int repl_filter_recv(seq_num tr_num, unsigned char *tr, int *tr_len, bool
recv_state = NEED_TCOMMIT;
}
}
-
/* if not NULL record */
if ((NEED_TCOMMIT == recv_state) || (!is_nontp && !is_null && ('0' != extr_rec[0] || '0' != extr_rec[1])))
{
recv_state = NEED_TCOMMIT;
while ('0' != extr_rec[0] || '9' != extr_rec[1]) /* while not TCOM record */
{
- if (SS_NORMAL != (status = repl_filter_recv_line(extr_rec, &extr_reclen,
- ZWR_EXP_RATIO(MAX_LOGI_JNL_REC_SIZE), send_done)))
- {
- assertpro(EREPL_FILTERNOSPC != repl_errno); /* why didn't we pre-allocate enough memory? */
+ if (SS_NORMAL != (status = repl_filter_recv_line(extr_rec, &extr_reclen, extr_bufsiz, send_done)))
return status;
- }
/* We don't want a null transaction inside a tp so get rid of it */
- if ('0' == extr_rec[0] && '0' == extr_rec[1]) continue;
+ if ('0' == extr_rec[0] && '0' == extr_rec[1])
+ continue;
+ if ((extr_len + extr_reclen) > recv_extract_bufsiz)
+ { /* Expand recv_extract_buff linearly */
+ recv_extract_bufsiz += (2 * MAX_ONE_JREC_EXTRACT_BUFSIZ);
+ assertpro(recv_extract_bufsiz > (extr_len + extr_reclen));
+ tmp = malloc(recv_extract_bufsiz);
+ memcpy(tmp, recv_extract_buff, extr_len);
+ free(recv_extract_buff);
+ recv_extract_buff = tmp;
+ }
+ assertpro(recv_extract_bufsiz >= (extr_len + extr_reclen));
memcpy(recv_extract_buff + extr_len, extr_rec, extr_reclen);
extr_len += extr_reclen;
rec_cnt++;
REPL_DEBUG_ONLY(extr_rec[extr_reclen] = '\0';)
- REPL_DPRINT5("rec_cnt: %d\textr_reclen: %d\textr_len: %d\t%s", rec_cnt,
- extr_reclen, extr_len, extr_rec);
+ REPL_DPRINT5("rec_cnt: %d\textr_reclen: %d\textr_len: %d\t%s", rec_cnt, extr_reclen, extr_len, extr_rec);
}
tcom_len = extr_reclen;
rec_cnt--;
@@ -895,7 +937,6 @@ static int repl_filter_recv(seq_num tr_num, unsigned char *tr, int *tr_len, bool
if (0 < rec_cnt)
{
extr_ptr = recv_extract_buff;
-
/* if unwrap_nontp is TRUE and rec_cnt is one then remove the wrapper added by the filter */
if (TRUE == unwrap_nontp)
{
@@ -904,26 +945,34 @@ static int repl_filter_recv(seq_num tr_num, unsigned char *tr, int *tr_len, bool
extr_ptr = recv_extract_buff + firstrec_len; /* Eliminate the dummy TSTART */
extr_len -= firstrec_len;
extr_len -= tcom_len; /* Eliminate the dummy TCOMMIT */
- }
- else /* a dummy TCOMMIT not allowed for a created multi-line transaction */
+ } else /* a dummy TCOMMIT not allowed for a created multi-line transaction */
{
if (DUMMY_TCOMMIT_LENGTH == tcom_len)
+ {
+ assert(WBTEST_EXTFILTER_INDUCE_ERROR == gtm_white_box_test_case_number);
return (repl_errno = EREPL_FILTERBADCONV);
+ }
}
}
extr_ptr[extr_len] = '\0'; /* terminate with null for ext2jnlcvt */
- if ((NULL == (tr_end = ext2jnlcvt(extr_ptr, extr_len, (jnl_record *)tr, save_jnl_seqno, save_strm_seqno)))
- || (save_jnl_seqno != GET_JNL_SEQNO(tr))
- || (save_strm_seqno != GET_STRM_SEQNO(tr)))
+ if ((NULL == (tr_end = ext2jnlcvt(extr_ptr, extr_len, tr, tr_bufsize, save_jnl_seqno, save_strm_seqno)))
+ || (save_jnl_seqno != GET_JNL_SEQNO(*tr)) || (save_strm_seqno != GET_STRM_SEQNO(*tr)))
+ {
+ assert(FALSE);
return (repl_errno = EREPL_FILTERBADCONV);
- *tr_len = (int4)(tr_end - (char *)&tr[0]);
+ }
+ assert((tr_end - *tr) <= *tr_bufsize);
+ *tr_len = tr_end - *tr;
/* TCOM record for non TP converted to TP must have the same seqno as the original non TP record */
if (TRUE == unwrap_nontp && 1 < rec_cnt)
{ /* tr_end points past the tcom record so need to back up the length of the tcom record */
tcom_ptr = tr_end - TCOM_RECLEN;
if (QWNE(save_jnl_seqno, ((struct_jrec_tcom *)tcom_ptr)->token_seq.jnl_seqno) ||
QWNE(save_strm_seqno, ((struct_jrec_tcom *)tcom_ptr)->strm_seqno))
+ {
+ assert(FALSE);
return (repl_errno = EREPL_FILTERBADCONV);
+ }
}
} else /* 0 == rec_cnt */
{ /* Transaction filtered out, put a JRT_NULL record; the prefix.{pini_addr,time,tn} fields are not filled in as they
@@ -931,7 +980,7 @@ static int repl_filter_recv(seq_num tr_num, unsigned char *tr, int *tr_len, bool
*/
QWASSIGN(null_jnlrec.jnl_seqno, save_jnl_seqno);
QWASSIGN(null_jnlrec.strm_seqno, save_strm_seqno);
- memcpy(tr, (char *)&null_jnlrec, NULL_RECLEN);
+ memcpy(*tr, (char *)&null_jnlrec, NULL_RECLEN);
*tr_len = NULL_RECLEN;
/* Reset read pointers to avoid the subsequent records from being wrongly interpreted */
assert(srv_line_end <= srv_read_end);
@@ -941,7 +990,7 @@ static int repl_filter_recv(seq_num tr_num, unsigned char *tr, int *tr_len, bool
return(SS_NORMAL);
}
-int repl_filter(seq_num tr_num, unsigned char *tr, int *tr_len, int bufsize)
+int repl_filter(seq_num tr_num, unsigned char **tr, int *tr_len, int *tr_bufsize)
{
int status;
boolean_t try_send = TRUE;
@@ -957,8 +1006,8 @@ int repl_filter(seq_num tr_num, unsigned char *tr, int *tr_len, int bufsize)
struct pollfd poll_fdlist[1];
#endif
struct timeval repl_filter_poll_interval;
- /* */
+ assert(*tr_len <= *tr_bufsize);
recv_state = FIRST_RECV;
while ((FALSE == send_done) || (FALSE == recv_done))
{
@@ -1002,7 +1051,7 @@ int repl_filter(seq_num tr_num, unsigned char *tr, int *tr_len, int bufsize)
continue; /* when select is on receive then try it */
}
}
- status = repl_filter_send(tr_num, tr, *tr_len, first_send);
+ status = repl_filter_send(tr_num, *tr, *tr_len, first_send);
first_send = FALSE;
if (MORE_TO_TRANSFER == status)
{
@@ -1058,7 +1107,7 @@ int repl_filter(seq_num tr_num, unsigned char *tr, int *tr_len, int bufsize)
}
}
- status = repl_filter_recv(tr_num, tr, tr_len, send_done);
+ status = repl_filter_recv(tr_num, tr, tr_len, tr_bufsize, send_done);
if (MORE_TO_TRANSFER == status)
{
if (FALSE == send_done)
@@ -1152,7 +1201,7 @@ void repl_check_jnlver_compat(UNIX_ONLY(boolean_t same_endianness))
# endif
}
-static void upgrd_V19_hasht_xecute_string_to_V22(uchar_ptr_t jb, uchar_ptr_t cb, jnl_string *keystr, char *xecute_val_ptr,
+static void upgrd_V19_hasht_xecute_string_to_V24(uchar_ptr_t jb, uchar_ptr_t cb, jnl_string *keystr, char *xecute_val_ptr,
uint4 *conv_reclen)
{ /* Upgrade the ^#t("GBL",1,"XECUTE") node's value to the xecute string format supported in V5.4-002 (and later).
* Before V5.4-002, the xecute string is stored as-is in the database. But, from V5.4-002, the xecute string is
@@ -1249,8 +1298,8 @@ static void upgrd_V19_hasht_xecute_string_to_V22(uchar_ptr_t jb, uchar_ptr_t cb,
* that JRT_ZTRIG records are allowed here. JRT_ZTRIG is very similar to a JRT_KILL record
* in that it has a "struct_jrec_upd" layout and only the key/node (no value).
*
- * V22/V23 format
- * -----------
+ * V22/V23/V24 format
+ * -------------------
* struct_jrec_upd layout is as follows.
* offset = 0000 [0x0000] size = 0024 [0x0018] ----> prefix
* offset = 0024 [0x0018] size = 0008 [0x0008] ----> token_seq
@@ -1275,21 +1324,21 @@ static void upgrd_V19_hasht_xecute_string_to_V22(uchar_ptr_t jb, uchar_ptr_t cb,
* offset = 0044 [0x002c] size = 0004 [0x0004] ----> suffix
*/
-/* Convert a transaction from jnl version 17 or 18 (V5.0-000 through V5.3-004A) to 22/23 (V5.5-000 onwards)
+/* Convert a transaction from jnl version V17 or V18 (V5.0-000 through V5.3-004A) to V24 (V6.2-000 onwards)
* Differences between the two versions:
* ------------------------------------
- * (a) struct_jrec_upd in V22 is 16 bytes more than V17 (8 byte strm_seqno, 4 byte update_num and 2 byte num_participants field).
+ * (a) struct_jrec_upd in V24 is 16 bytes more than V17 (8 byte strm_seqno, 4 byte update_num and 2 byte num_participants field).
* Since every jnl record is 8-byte aligned, the difference is actually 16 bytes (and not 14).
* This means, we need to have 16 more bytes in the conversion buffer for SET/KILL/ZKILL/ZTRIG type of records.
- * (b) struct_jrec_tcom in V22 is 8 bytes more than V17 (8 byte strm_seqno).
+ * (b) struct_jrec_tcom in V24 is 8 bytes more than V17 (8 byte strm_seqno).
* This means, we need to have 8 more bytes in the conversion buffer for TCOM type of records.
- * (c) struct_jrec_null in V22 is 8 bytes more than V17 (8 byte strm_seqno).
+ * (c) struct_jrec_null in V24 is 8 bytes more than V17 (8 byte strm_seqno).
* This means, we need to have 8 more bytes in the conversion buffer for NULL type of records.
* (d) If the null collation is different between primary and secondary (null_subs_xform) then appropriate conversion
* is needed
* Reformat accordingly.
*/
-int jnl_v17TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+int jnl_v17TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
{
unsigned char *jb, *cb, *cstart, *jstart;
enum jnl_record_type rectype;
@@ -1334,7 +1383,7 @@ int jnl_v17TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(SIZEOF(token_seq_t) == SIZEOF(seq_num));
t_len = (JREC_PREFIX_SIZE + SIZEOF(token_seq_t));
memcpy(cb, jb, t_len);
- ((jrec_prefix *)cb)->forwptr = conv_reclen; /* forwptr will be different between V17 and V22 due to new length */
+ ((jrec_prefix *)cb)->forwptr = conv_reclen; /* forwptr will be different between V17 and V24 due to new length */
cb += t_len;
jb += t_len;
/* Initialize 8-byte "strm_seqno" (common to TCOM/NULL/SET/KILL/ZKILL/ZTRIG jnl records) to 0 */
@@ -1344,13 +1393,13 @@ int jnl_v17TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(0 < tail_minus_suffix_len);
if (is_set_kill_zkill_ztrig)
{ /* Initialize "update_num" member */
- INITIALIZE_V22_UPDATE_NUM_FROM_V17(cstart, cb, jstart, jb, tset_num, update_num, rectype);
+ INITIALIZE_V24_UPDATE_NUM_FROM_V17(cstart, cb, jstart, jb, tset_num, update_num, rectype);
/* Initialize "mumps_node" member */
- INITIALIZE_V22_MUMPS_NODE_FROM_V17(cstart, cb, jstart, jb, tail_minus_suffix_len, FALSE);
+ INITIALIZE_V24_MUMPS_NODE_FROM_V17(cstart, cb, jstart, jb, tail_minus_suffix_len, FALSE);
} else if (JRT_TCOM == rectype)
{
assert((jb - jstart) == (OFFSETOF(struct_jrec_tcom, token_seq) + SIZEOF(token_seq_t)));
- INITIALIZE_V22_TCOM_FROM_V17(cstart, cb, jstart, jb, tcom_num, tset_num, update_num);
+ INITIALIZE_V24_TCOM_FROM_V17(cstart, cb, jstart, jb, tcom_num, tset_num, update_num);
} else
{ /* NULL record : only "filler" member remains so no need to do any copy */
cb += tail_minus_suffix_len;
@@ -1360,7 +1409,7 @@ int jnl_v17TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert((cb - cstart) == (conv_reclen - JREC_SUFFIX_SIZE));
assert((jb - jstart) == (reclen - JREC_SUFFIX_SIZE));
/* Initialize "suffix" member */
- INITIALIZE_V22_JREC_SUFFIX(cstart, cb, jstart, jb, conv_reclen); /* side-effect: cb and jb pointers incremented */
+ INITIALIZE_V24_JREC_SUFFIX(cstart, cb, jstart, jb, conv_reclen); /* side-effect: cb and jb pointers incremented */
/* Nothing more to be initialized for this record */
assert(ROUND_UP2(conv_reclen, JNL_REC_START_BNDRY) == conv_reclen);
assert(cb == cstart + conv_reclen);
@@ -1378,22 +1427,22 @@ int jnl_v17TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
return(status);
}
-/* Convert a transaction from jnl version 22/23 (V5.5-000 onwards) to 17 or 18 (V5.0-000 through V5.3-004A)
- * For differences between the two versions, see the comment in jnl_v17TOv22. In addition, take care of the following.
- * (a) Since the remote side (V17) does NOT support triggers, skip ^#t, ZTWORM and ZTRIG journal records & reset nodeflags (if set).
- * If the entire transaction consists of skipped records, send a NULL record instead.
+/* Convert a transaction from jnl version V24 (V6.2-000 onwards) to V17 or V18 (V5.0-000 through V5.3-004A)
+ * For differences between the two versions, see the comment in jnl_v17TOv24. In addition, take care of the following.
+ * (a) Since the remote side (V17) does NOT support triggers, skip ^#t, ZTWORM/LGTRIG/ZTRIG journal records
+ * & reset nodeflags (if set). If the entire transaction consists of skipped records, send a NULL record instead.
*
* Note: Although (1) is trigger specific, the logic should be available for trigger non-supporting platorms as well to
* handle replication scenarios like V5.4-001 (TS) -> V5.4-002 (NTS) -> V4.4-004 (NTS) where TS indicates a trigger supporting
* platform and NTS indicates either a version without trigger support OR is running on trigger non-supporting platform.
*/
-int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+int jnl_v24TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
{
unsigned char *jb, *cb, *cstart, *jstart;
enum jnl_record_type rectype;
int status, reclen, conv_reclen;
uint4 jlen, t_len, tail_minus_suffix_len, tupd_num = 0, tcom_num = 0;
- boolean_t is_set_kill_zkill_ztrig, promote_uupd_to_tupd;
+ boolean_t is_set_kill_zkill_ztrig, promote_uupd_to_tupd, hasht_seen;
jrec_prefix *prefix;
seq_num this_upd_seqno;
uint4 trigupd_type = NO_TRIG_JREC;
@@ -1409,6 +1458,8 @@ int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
QWASSIGN(this_upd_seqno, seq_num_zero);
promote_uupd_to_tupd = FALSE;
assert(is_src_server);
+ hasht_seen = FALSE;
+ /* receiver_supports_triggers = FALSE; */ /* V17 = pre-V5.4-000 and so does not support triggers */
while (JREC_PREFIX_SIZE <= jlen)
{
assert(0 == ((UINTPTR_T)jb % SIZEOF(uint4)));
@@ -1422,7 +1473,7 @@ int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
if (QWEQ(this_upd_seqno, seq_num_zero))
QWASSIGN(this_upd_seqno, GET_JNL_SEQNO(jb));
assert(IS_REPLICATED(rectype));
- if (!IS_ZTWORM(rectype) && !IS_ZTRIG(rectype))
+ if (!IS_ZTWORM(rectype) && !IS_LGTRIG(rectype) && !IS_ZTRIG(rectype))
{
is_set_kill_zkill_ztrig = IS_SET_KILL_ZKILL_ZTRIG(rectype);
assert(is_set_kill_zkill_ztrig || (JRT_TCOM == rectype) || (JRT_NULL == rectype));
@@ -1434,7 +1485,7 @@ int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(SIZEOF(token_seq_t) == SIZEOF(seq_num));
t_len = (JREC_PREFIX_SIZE + SIZEOF(token_seq_t));
memcpy(cb, jb, t_len);
- ((jrec_prefix *)cb)->forwptr = conv_reclen; /* forwptr will be different between V17 and V22 */
+ ((jrec_prefix *)cb)->forwptr = conv_reclen; /* forwptr will be different between V17 and V24 */
cb += t_len;
jb += t_len;
if (is_set_kill_zkill_ztrig)
@@ -1445,7 +1496,7 @@ int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
)
assert((cb - cstart) == (OFFSETOF(struct_jrec_upd, token_seq) + SIZEOF(token_seq_t)));
/* side-effect: increments cb and jb and GTM Null Collation or Standard Null Collation applied */
- INITIALIZE_V17_MUMPS_NODE_FROM_V22(cstart, cb, jstart, jb, trigupd_type, FALSE);
+ INITIALIZE_V17_MUMPS_NODE_FROM_V24(cstart, cb, jstart, jb, trigupd_type, FALSE);
if (HASHT_JREC == trigupd_type)
{ /* Journal record has a #t global. #t records are not replicated if the secondary does not
* support triggers. However, $ZTRIGGER() usages within TP can cause ^#t records to be
@@ -1458,6 +1509,7 @@ int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
jlen -= reclen;
if (IS_TUPD(rectype))
promote_uupd_to_tupd = TRUE;
+ hasht_seen = TRUE;
continue;
}
if (IS_TUPD(rectype))
@@ -1487,7 +1539,7 @@ int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
/* We better have initialized the "prefix" and "token_seq" */
assert((cb - cstart) == (OFFSETOF(struct_jrec_tcom, token_seq) + SIZEOF(token_seq_t)));
- INITIALIZE_V17_TCOM_FROM_V22(cstart, cb, jstart, jb); /* side-effect: increments cb and jb */
+ INITIALIZE_V17_TCOM_FROM_V24(cstart, cb, jstart, jb); /* side-effect: increments cb and jb */
} else
{
assert (JRT_NULL == rectype);
@@ -1505,15 +1557,15 @@ int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(ROUND_UP2(conv_reclen, JNL_REC_START_BNDRY) == conv_reclen);
assert(cb == cstart + conv_reclen);
} else
- { /* $ZTWORMHOLE jnl record does not exist in previous V15 so skip converting it */
+ { /* $ZTWORMHOLE/ZTRIG/LGTRIG jnl record does not exist in V17 so skip converting it */
assert((cb == cstart) && (jb == jstart)); /* No conversions yet */
jb = jstart + reclen;
- /* If this is a TUPD rectype (actually JRT_TZTWORM) then the next UUPD has to be promoted to a TUPD type
+ /* If this is a TUPD rectype then the next UUPD has to be promoted to a TUPD type
* to account for the balance in TUPD and TCOM records
*/
if (IS_TUPD(rectype))
{
- assert((JRT_TZTWORM == rectype) || (JRT_TZTRIG == rectype));
+ assert((JRT_TZTWORM == rectype) || (JRT_TLGTRIG == rectype) || (JRT_TZTRIG == rectype));
promote_uupd_to_tupd = TRUE;
}
}
@@ -1522,43 +1574,48 @@ int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
assert((0 == jlen) || (-1 == status));
assert((jb == (jnl_buff + *jnl_len)) || (-1 == status));
- if ((-1 != status) && (cb == conv_buff))
- { /* No conversion happened. Currently this is possible if
- * (a) All the records are ^#t.
- * (b) If the only records in a transaction are ZTRIG records and a TCOM record.
- * In both the above cases we need to send a NULL record instead.
- */
- assert((HASHT_JREC == trigupd_type) || (FALSE == non_ztrig_rec_found));
+ if (-1 != status)
+ {
GTMTRIG_ONLY(
- if (!(TREF(replgbl)).trig_replic_suspect_seqno)
+ if (hasht_seen && !(TREF(replgbl)).trig_replic_suspect_seqno)
(TREF(replgbl)).trig_replic_suspect_seqno = this_upd_seqno;
)
- prefix = (jrec_prefix *)(cb);
- if (V17_NULL_RECLEN > conv_bufsiz)
- {
- repl_errno = EREPL_INTLFILTER_NOSPC;
- status = -1;
- } else
- INITIALIZE_V17_NULL_RECORD(prefix, cb, this_upd_seqno); /* note: cb is incremented by V17_NULL_RECLEN */
+ if (cb == conv_buff)
+ { /* No conversion happened. Currently this is possible if
+ * (a) All the records are ^#t.
+ * (b) If the only records in a transaction are ZTRIG records and a TCOM record.
+ * In both the above cases we need to send a NULL record instead.
+ */
+ assert((HASHT_JREC == trigupd_type) || (FALSE == non_ztrig_rec_found));
+ prefix = (jrec_prefix *)(cb);
+ if (V17_NULL_RECLEN > conv_bufsiz)
+ {
+ repl_errno = EREPL_INTLFILTER_NOSPC;
+ status = -1;
+ } else
+ INITIALIZE_V17_NULL_RECORD(prefix, cb, this_upd_seqno); /* note: cb is incremented
+ * by V17_NULL_RECLEN */
+ }
}
*conv_len = (uint4)(cb - conv_buff);
assert((0 < *conv_len) || (-1 == status));
return(status);
}
-/* Convert a transaction from jnl version 19 or 20 (V5.4-000 through V5.4-001) to 22/23 (V5.5-000 onwards)
+/* Convert a transaction from jnl version V19 or V20 (V5.4-000 through V5.4-001) to V24 (V6.2-000 onwards)
* Differences between the two versions:
- * ------------------------------------
- * (a) struct_jrec_upd, struct_jrec_tcom and struct_jrec_null in V22 is 8 bytes more than V19 (8 byte strm_seqno).
+ * -------------------------------------
+ * (a) struct_jrec_upd, struct_jrec_tcom and struct_jrec_null in V24 is 8 bytes more than V19 (8 byte strm_seqno).
* This means, we need to have 8 more bytes in the conversion buffer for NULL/TCOM/SET/KILL/ZKILL type of records.
- * (b) If the receiver side does NOT support triggers, then skip ^#t or ZTWORM journal records & reset nodeflags (if set).
+ * (b) If the receiver side does NOT support triggers, then skip ^#t/ZTWORM journal records & reset nodeflags (if set).
+ * Note that V19 did not support ZTRIG or LGTRIG records so dont need to check for them.
* If the entire transaction consists of skipped records, send a NULL record instead.
* (c) If receiver side does support triggers, then fix ^#t("GBL","#LABEL") and ^#t("GBL",1,"XECUTE") to reflect newer format.
*
* Note : For both (a) and (b), ZTRIG type of records are not possible in V19 (they start only from V21).
* Reformat accordingly.
*/
-int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+int jnl_v19TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
{
unsigned char *jb, *cb, *cstart, *jstart, *mumps_node_ptr;
char *keyend, *ptr;
@@ -1568,7 +1625,7 @@ int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
jrec_prefix *prefix;
seq_num this_upd_seqno;
uint4 trigupd_type = NO_TRIG_JREC;
- boolean_t promote_uupd_to_tupd, receiver_supports_triggers;
+ boolean_t promote_uupd_to_tupd, receiver_supports_triggers, hasht_seen;
jnl_string *keystr;
DCL_THREADGBL_ACCESS;
@@ -1584,6 +1641,7 @@ int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
* supports triggers is equal to checking whether the LOCAL side supports triggers.
*/
receiver_supports_triggers = LOCAL_TRIGGER_SUPPORT;
+ hasht_seen = FALSE;
while (JREC_PREFIX_SIZE <= jlen)
{
assert(0 == ((UINTPTR_T)jb % SIZEOF(uint4)));
@@ -1621,22 +1679,26 @@ int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
} else if (HASHT_JREC == trigupd_type)
{ /* Journal record has a #t global. #t records are not replicated if the secondary does not
- * support triggers. Instead a NULL record needs to be sent
+ * support triggers. Instead a NULL record needs to be sent. No need to uupd->tupd
+ * promotion since in GT.M versions for V19 format (pre-V5.4-002) you cannot mix ^#t
+ * and non-^#t records in the same TP transaction.
*/
assert((jb == jnl_buff) && (cb == conv_buff)); /* if ^#t, we better see it as the first
* journal record */
+ hasht_seen = TRUE;
break;
}
/* Copy "prefix" and "token_seq" field */
memcpy(cb, jb, V19_UPDATE_NUM_OFFSET);
- /* Initialize 8-byte "strm_seqno" in V22 format record (not present in V19 format) */
+ /* Initialize 8-byte "strm_seqno" in V24 format record (not present in V19 format) */
((struct_jrec_upd *)(cb))->strm_seqno = 0;
- /* Copy rest of V19 record into V22 record (rest of the fields have same layout) */
+ /* Copy rest of V19 record into V24 record (rest of the fields have same layout) */
memcpy(cb + V19_UPDATE_NUM_OFFSET + 8, jb + V19_UPDATE_NUM_OFFSET,
conv_reclen - 8 - V19_UPDATE_NUM_OFFSET);
- mumps_node_ptr = cstart + V22_MUMPS_NODE_OFFSET;
- if ((HASHT_JREC == trigupd_type) && receiver_supports_triggers)
+ mumps_node_ptr = cstart + V24_MUMPS_NODE_OFFSET;
+ if (HASHT_JREC == trigupd_type)
{ /* ^#t record */
+ assert(receiver_supports_triggers);
keystr = (jnl_string *)mumps_node_ptr;
keyend = &keystr->text[keystr->length - 1];
if (!MEMCMP_LIT((keyend - LITERAL_HASHLABEL_LEN), LITERAL_HASHLABEL))
@@ -1657,7 +1719,7 @@ int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(IS_SET(rectype)); /* This better be a SET record */
if (IS_SET(rectype))
{ /* do the upgrade in PRO only if this is a SET record */
- upgrd_V19_hasht_xecute_string_to_V22(jb, cb, keystr, keyend + 1,
+ upgrd_V19_hasht_xecute_string_to_V24(jb, cb, keystr, keyend + 1,
&conv_reclen);
assert(0 == conv_reclen % JNL_REC_START_BNDRY);
}
@@ -1687,9 +1749,9 @@ int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
/* Copy "prefix" and "token_seq" field */
memcpy(cb, jb, V19_TCOM_FILLER_SHORT_OFFSET);
- /* Initialize 8-byte "strm_seqno" in V22 format record (not present in V19 format) */
+ /* Initialize 8-byte "strm_seqno" in V24 format record (not present in V19 format) */
((struct_jrec_tcom *)(cb))->strm_seqno = 0;
- /* Copy rest of V19 record into V22 record (rest of the fields have same layout) */
+ /* Copy rest of V19 record into V24 record (rest of the fields have same layout) */
memcpy(cb + V19_TCOM_FILLER_SHORT_OFFSET + 8, jb + V19_TCOM_FILLER_SHORT_OFFSET,
conv_reclen - 8 - V19_TCOM_FILLER_SHORT_OFFSET);
((struct_jrec_tcom *)(cb))->num_participants = tupd_num;
@@ -1700,9 +1762,9 @@ int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
memcpy(cb, jb, conv_reclen);
/* Copy "prefix" and "jnl_seqno" field */
memcpy(cb, jb, V19_NULL_FILLER_OFFSET);
- /* Initialize 8-byte "strm_seqno" in V22 format record (not present in V19 format) */
+ /* Initialize 8-byte "strm_seqno" in V24 format record (not present in V19 format) */
((struct_jrec_tcom *)(cb))->strm_seqno = 0;
- /* Copy rest of V19 record into V22 record (rest of the fields have same layout) */
+ /* Copy rest of V19 record into V24 record (rest of the fields have same layout) */
memcpy(cb + V19_NULL_FILLER_OFFSET + 8, jb + V19_NULL_FILLER_OFFSET,
conv_reclen - 8 - V19_NULL_FILLER_OFFSET);
}
@@ -1727,22 +1789,25 @@ int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
assert((0 == jlen) || (-1 == status) || (HASHT_JREC == trigupd_type));
assert((jb == (jnl_buff + *jnl_len)) || (-1 == status) || (HASHT_JREC == trigupd_type));
- if ((-1 != status) && (cb == conv_buff))
- { /* No conversion happened. Currently this is possible ONLY if all the records are ^#t records. Need to send
- * NULL record
- */
- assert(!receiver_supports_triggers && (HASHT_JREC == trigupd_type));
+ if (-1 != status)
+ {
GTMTRIG_ONLY(
- if (!(TREF(replgbl)).trig_replic_suspect_seqno)
+ if (hasht_seen && !(TREF(replgbl)).trig_replic_suspect_seqno)
(TREF(replgbl)).trig_replic_suspect_seqno = this_upd_seqno;
)
- prefix = (jrec_prefix *)(cb);
- if (V22_NULL_RECLEN > conv_bufsiz)
- {
- repl_errno = EREPL_INTLFILTER_NOSPC;
- status = -1;
- } else
- INITIALIZE_V22_NULL_RECORD(prefix, cb, this_upd_seqno, 0); /* Side-effect: cb is incremented */
+ if (cb == conv_buff)
+ { /* No conversion happened. Currently this is possible ONLY if all the records are ^#t records.
+ * Need to send a NULL record.
+ */
+ assert(!receiver_supports_triggers && (HASHT_JREC == trigupd_type));
+ prefix = (jrec_prefix *)(cb);
+ if (V24_NULL_RECLEN > conv_bufsiz)
+ {
+ repl_errno = EREPL_INTLFILTER_NOSPC;
+ status = -1;
+ } else
+ INITIALIZE_V24_NULL_RECORD(prefix, cb, this_upd_seqno, 0); /* Side-effect: cb is incremented */
+ }
}
*conv_len = (uint4)(cb - conv_buff);
assert((0 < *conv_len) || (-1 == status));
@@ -1753,14 +1818,15 @@ int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
return(status);
}
-/* Convert a transaction from jnl version 22/23 (V5.5-000 onwards) to 19 or 20 (V5.4-000 through V5.4-001)
- * For differences between the two versions, see the comment in jnl_v19TOv22. In addition, take care of the following.
- * a) Skip ZTRIG records unconditionally as V19 (trigger enabled or not does not matter) does not support them.
- * b) If the remote side does NOT support triggers, then skip ^#t or ZTWORM journal records.
+/* Convert a transaction from jnl version V24 (V6.2-000 onwards) to V19 or V20 (V5.4-000 through V5.4-001)
+ * For differences between the two versions, see the comment in jnl_v19TOv24. In addition, take care of the following.
+ * (a) Skip ZTRIG records unconditionally as V19 (trigger enabled or not does not matter) does not support them.
+ * (b) If the remote side does NOT support triggers, then skip ^#t/ZTWORM/ZTRIG/LGTRIG journal records.
* If the entire transaction consists of skipped records, send a NULL record instead.
- * (c) If remote side does support triggers, then fix ^#t("GBL","#LABEL") and ^#t("GBL",1,"XECUTE") to reflect older format.
+ * (c) If remote side does support triggers, then fix ^#t("GBL","#LABEL") and ^#t("GBL",1,"XECUTE") to reflect older format
+ * and skip LGTRIG journal records as they are not known to the older journal format.
*/
-int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+int jnl_v24TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
{
unsigned char *jb, *cb, *cstart, *jstart, *mumps_node_ptr;
char *keyend, *ptr;
@@ -1771,6 +1837,7 @@ int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
seq_num this_upd_seqno;
uint4 trigupd_type = NO_TRIG_JREC;
boolean_t promote_uupd_to_tupd, hasht_update_found, normal_update_found, receiver_supports_triggers;
+ boolean_t hasht_seen;
DEBUG_ONLY(boolean_t non_ztrig_rec_found = FALSE;)
jnl_string *keystr;
DCL_THREADGBL_ACCESS;
@@ -1782,6 +1849,7 @@ int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
jlen = *jnl_len;
QWASSIGN(this_upd_seqno, seq_num_zero);
promote_uupd_to_tupd = hasht_update_found = normal_update_found = FALSE;
+ hasht_seen = FALSE;
assert(is_src_server);
/* Since this filter function will be invoked only on the source side, the check for whether the receiver
* supports triggers is equal to checking whether the REMOTE side supports triggers.
@@ -1802,16 +1870,16 @@ int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(IS_REPLICATED(rectype));
if (IS_TUPD(rectype))
promote_uupd_to_tupd = FALSE;
- if (IS_ZTRIG(rectype) || (IS_ZTWORM(rectype) && !receiver_supports_triggers))
- { /* ZTRIG record is not supported by remote side (as it is V19) OR $ZTWORMHOLE jnl record cannot be handled
- * by remote side as it does not support triggers so skip converting in either case.
- * If this is a TUPD rectype (actually JRT_TZTWORM/JRT_TZTRIG) then the next UUPD has to be promoted to a
- * TUPD type to account for the balance in TUPD and TCOM records
+ if (IS_ZTRIG(rectype) || IS_LGTRIG(rectype) || (IS_ZTWORM(rectype) && !receiver_supports_triggers))
+ { /* ZTRIG or LGTRIG record is not supported by remote side (as it is V19)
+ * OR $ZTWORMHOLE jnl record cannot be handled by remote side as it does not support triggers
+ * so skip converting in either case. If this is a TUPD rectype (actually JRT_TZTWORM/JRT_TZTRIG)
+ * then the next UUPD has to be promoted to a TUPD type to account for the balance in TUPD and TCOM records.
*/
assert((cb == cstart) && (jb == jstart)); /* No conversions yet */
if (IS_TUPD(rectype))
{
- assert((JRT_TZTWORM == rectype) || (JRT_TZTRIG == rectype));
+ assert((JRT_TZTWORM == rectype) || (JRT_TLGTRIG == rectype) || (JRT_TZTRIG == rectype));
promote_uupd_to_tupd = TRUE;
}
} else
@@ -1824,16 +1892,16 @@ int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(SIZEOF(token_seq_t) == SIZEOF(seq_num));
t_len = (JREC_PREFIX_SIZE + SIZEOF(token_seq_t));
memcpy(cb, jb, t_len);
- ((jrec_prefix *)cb)->forwptr = conv_reclen; /* forwptr will be different between V19 and V22 */
+ ((jrec_prefix *)cb)->forwptr = conv_reclen; /* forwptr will be different between V19 and V24 */
assert((jb + t_len - jstart) == OFFSETOF(struct_jrec_upd, strm_seqno));
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (IS_SET_KILL_ZKILL_ZTWORM(rectype))
{
assert((cb == cstart) && (jb == jstart));
DEBUG_ONLY(
if (!IS_ZTRIG(rectype))
non_ztrig_rec_found = TRUE;
)
- GET_JREC_UPD_TYPE(jb + V22_MUMPS_NODE_OFFSET, trigupd_type);
+ GET_JREC_UPD_TYPE(jb + V24_MUMPS_NODE_OFFSET, trigupd_type);
if (receiver_supports_triggers)
{
if (!normal_update_found)
@@ -1857,13 +1925,15 @@ int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
promote_uupd_to_tupd = TRUE;
jb = jb + reclen;
jlen -= reclen;
+ hasht_seen = TRUE;
continue;
}
/* t_len bytes have already been copied. Skip 8-byte strm_seqno (absent in V19) and copy rest */
memcpy(cb + t_len, jb + t_len + 8, conv_reclen - t_len);
mumps_node_ptr = (cb + V19_MUMPS_NODE_OFFSET);
- if ((HASHT_JREC == trigupd_type) && receiver_supports_triggers)
+ if (HASHT_JREC == trigupd_type)
{
+ assert(receiver_supports_triggers);
if (!hasht_update_found)
hasht_update_found = TRUE;
/* Since the secondary side is running on an older trigger-supporting version than the
@@ -1950,26 +2020,29 @@ int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
assert((0 == jlen) || (-1 == status));
assert((jb == (jnl_buff + *jnl_len)) || (-1 == status));
- if ((-1 != status) && (cb == conv_buff))
- { /* No conversion happened. Currently this is possible if
- * (a) All the records are ^#t.
- * (b) If the only records in a transaction are ZTRIG records and a TCOM record.
- * In both the above cases we need to send a NULL record instead.
- */
- assert((HASHT_JREC == trigupd_type) || (FALSE == non_ztrig_rec_found));
+ if (-1 != status)
+ {
GTMTRIG_ONLY(
- if (!(TREF(replgbl)).trig_replic_suspect_seqno)
+ if (hasht_seen && !(TREF(replgbl)).trig_replic_suspect_seqno)
(TREF(replgbl)).trig_replic_suspect_seqno = this_upd_seqno;
)
- prefix = (jrec_prefix *)(cb);
- if (NULL_RECLEN > conv_bufsiz)
- {
- repl_errno = EREPL_INTLFILTER_NOSPC;
- status = -1;
- } else
- { /* Create NULL record. Since the null record format is same for V17 and V19, it is safe to use the
- * below macro. Note: Side-effect: cb is incremented by below macro */
- INITIALIZE_V17_NULL_RECORD(prefix, cb, this_upd_seqno);
+ if (cb == conv_buff)
+ { /* No conversion happened. Currently this is possible if
+ * (a) All the records are ^#t.
+ * (b) If the only records in a transaction are ZTRIG records and a TCOM record.
+ * In both the above cases we need to send a NULL record instead.
+ */
+ assert((HASHT_JREC == trigupd_type) || (FALSE == non_ztrig_rec_found));
+ prefix = (jrec_prefix *)(cb);
+ if (NULL_RECLEN > conv_bufsiz)
+ {
+ repl_errno = EREPL_INTLFILTER_NOSPC;
+ status = -1;
+ } else
+ { /* Create NULL record. Since the null record format is same for V17 and V19, it is safe to use the
+ * below macro. Note: Side-effect: cb is incremented by below macro */
+ INITIALIZE_V17_NULL_RECORD(prefix, cb, this_upd_seqno);
+ }
}
}
*conv_len = (uint4)(cb - conv_buff);
@@ -1977,19 +2050,20 @@ int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
return status;
}
-/* Convert a transaction from jnl version 21 (V5.4-002 through V5.4-002B) to 22/23 (V5.5-000 onwards)
+/* Convert a transaction from jnl version V21 (V5.4-002 through V5.4-002B) to V24 (V6.2-000 onwards)
* Differences between the two versions:
- * ------------------------------------
- * (a) struct_jrec_upd, struct_jrec_tcom and struct_jrec_null in V22 is 8 bytes more than V21 due to 8 byte strm_seqno.
+ * -------------------------------------
+ * (a) struct_jrec_upd, struct_jrec_tcom and struct_jrec_null in V24 is 8 bytes more than V21 due to 8 byte strm_seqno.
* This means, we need to have 8 more bytes in the conversion buffer for NULL/TCOM/SET/KILL/ZKILL/ZTRIG type of records.
- * (b) If the receiver side does NOT support triggers, then skip ^#t or ZTWORM or ZTRIG journal records & reset nodeflags (if set).
+ * (b) If the receiver side does NOT support triggers, then skip ^#t/ZTWORM/ZTRIG journal records & reset nodeflags (if set).
+ * Note that V21 did not support LGTRIG records so dont need to check for them.
* If the entire transaction consists of skipped records, send a NULL record instead.
* Reformat accordingly.
- * Note: This function (jnl_v21TOv22) is somewhat similar to jnl_v19TOv22 except that ZTRIG records can be seen in v21
+ * Note: This function (jnl_v21TOv24) is somewhat similar to jnl_v19TOv24 except that ZTRIG records can be seen in v21
* whereas it cannot be in v19. In addition, no ^#t("GBL","#LABEL") or ^#t("GBL",1,"XECUTE") conversions are needed
- * since the ^#t format is unchanged between V21 and V22.
+ * since the ^#t format is unchanged between V21 and V24.
*/
-int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+int jnl_v21TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
{
unsigned char *jb, *cb, *cstart, *jstart, *mumps_node_ptr;
char *keyend, *ptr;
@@ -1999,7 +2073,7 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
jrec_prefix *prefix;
seq_num this_upd_seqno;
uint4 trigupd_type = NO_TRIG_JREC;
- boolean_t promote_uupd_to_tupd, receiver_supports_triggers;
+ boolean_t promote_uupd_to_tupd, receiver_supports_triggers, hasht_seen;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -2014,6 +2088,7 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
* supports triggers is equal to checking whether the LOCAL side supports triggers.
*/
receiver_supports_triggers = LOCAL_TRIGGER_SUPPORT;
+ hasht_seen = FALSE;
while (JREC_PREFIX_SIZE <= jlen)
{
assert(0 == ((UINTPTR_T)jb % SIZEOF(uint4)));
@@ -2043,10 +2118,10 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
} else
{
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype) || (JRT_TCOM == rectype) || (JRT_NULL == rectype));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_ZTRIG(rectype) || (JRT_TCOM == rectype) || (JRT_NULL == rectype));
conv_reclen = prefix->forwptr + 8; /* see comment (a) at top of function */
BREAK_IF_NOSPC((cb - conv_buff + conv_reclen), conv_bufsiz, status); /* check for available space */
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (IS_SET_KILL_ZKILL_ZTWORM_ZTRIG(rectype))
{
GET_JREC_UPD_TYPE((jb + V19_MUMPS_NODE_OFFSET), trigupd_type);
if (receiver_supports_triggers)
@@ -2062,7 +2137,7 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
} else if (HASHT_JREC == trigupd_type)
{ /* Journal record has a #t global. #t records are not replicated if the secondary
- * does not support triggers. Skip this record. See comment in jnl_v22TOv21 under similar
+ * does not support triggers. Skip this record. See comment in jnl_v24TOv21 under similar
* section for why the promotion of uupd to tupd is needed.
*/
if (IS_TUPD(rectype))
@@ -2070,17 +2145,18 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert((cb == cstart) && (jb == jstart));
jb = jb + reclen;
jlen -= reclen;
+ hasht_seen = TRUE;
continue;
}
/* Copy "prefix" and "token_seq" field. Since V21 is same as V19 fmt use the V19 macros */
memcpy(cb, jb, V19_UPDATE_NUM_OFFSET);
- /* Initialize 8-byte "strm_seqno" in V22 format record (not present in V21 format) */
+ /* Initialize 8-byte "strm_seqno" in V24 format record (not present in V21 format) */
((struct_jrec_upd *)(cb))->strm_seqno = 0;
- /* Copy rest of V21 (aka V19) record into V22 record (rest of the fields have same layout) */
+ /* Copy rest of V21 (aka V19) record into V24 record (rest of the fields have same layout) */
memcpy(cb + V19_UPDATE_NUM_OFFSET + 8, jb + V19_UPDATE_NUM_OFFSET,
conv_reclen - 8 - V19_UPDATE_NUM_OFFSET);
- mumps_node_ptr = cstart + V22_MUMPS_NODE_OFFSET;
- /* V21 and V22 have same ^#t("GBL","#LABEL") value so no need to fix like is done for V19 to V22 */
+ mumps_node_ptr = cstart + V24_MUMPS_NODE_OFFSET;
+ /* V21 and V24 have same ^#t("GBL","#LABEL") value so no need to fix like is done for V19 to V24 */
if (!receiver_supports_triggers)
((jnl_string *)mumps_node_ptr)->nodeflags = 0;
NULLSUBSC_TRANSFORM_IF_NEEDED(mumps_node_ptr);
@@ -2105,9 +2181,9 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
/* Copy "prefix" and "token_seq" field */
memcpy(cb, jb, V19_TCOM_FILLER_SHORT_OFFSET);
- /* Initialize 8-byte "strm_seqno" in V22 format record (not present in V19 format) */
+ /* Initialize 8-byte "strm_seqno" in V24 format record (not present in V19 format) */
((struct_jrec_tcom *)(cb))->strm_seqno = 0;
- /* Copy rest of V19 record into V22 record (rest of the fields have same layout) */
+ /* Copy rest of V19 record into V24 record (rest of the fields have same layout) */
memcpy(cb + V19_TCOM_FILLER_SHORT_OFFSET + 8, jb + V19_TCOM_FILLER_SHORT_OFFSET,
conv_reclen - 8 - V19_TCOM_FILLER_SHORT_OFFSET);
((struct_jrec_tcom *)(cb))->num_participants = tupd_num;
@@ -2118,9 +2194,9 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
memcpy(cb, jb, conv_reclen);
/* Copy "prefix" and "jnl_seqno" field */
memcpy(cb, jb, V19_NULL_FILLER_OFFSET);
- /* Initialize 8-byte "strm_seqno" in V22 format record (not present in V19 format) */
+ /* Initialize 8-byte "strm_seqno" in V24 format record (not present in V19 format) */
((struct_jrec_tcom *)(cb))->strm_seqno = 0;
- /* Copy rest of V19 record into V22 record (rest of the fields have same layout) */
+ /* Copy rest of V19 record into V24 record (rest of the fields have same layout) */
memcpy(cb + V19_NULL_FILLER_OFFSET + 8, jb + V19_NULL_FILLER_OFFSET,
conv_reclen - 8 - V19_NULL_FILLER_OFFSET);
}
@@ -2134,22 +2210,25 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
assert((0 == jlen) || (-1 == status));
assert((jb == (jnl_buff + *jnl_len)) || (-1 == status));
- if ((-1 != status) && (cb == conv_buff))
- { /* No conversion happened. Currently this is possible ONLY if the secondary does not support triggers and
- * all the records are trigger related records (^#t or ZTRIG or ZTWORM). Need to send NULL record instead.
- */
- assert(!receiver_supports_triggers);
+ if (-1 != status)
+ {
GTMTRIG_ONLY(
- if (!(TREF(replgbl)).trig_replic_suspect_seqno)
+ if (hasht_seen && !(TREF(replgbl)).trig_replic_suspect_seqno)
(TREF(replgbl)).trig_replic_suspect_seqno = this_upd_seqno;
)
- prefix = (jrec_prefix *)(cb);
- if (V22_NULL_RECLEN > conv_bufsiz)
- {
- repl_errno = EREPL_INTLFILTER_NOSPC;
- status = -1;
- } else
- INITIALIZE_V22_NULL_RECORD(prefix, cb, this_upd_seqno, 0); /* Side-effect: cb is incremented */
+ if (cb == conv_buff)
+ { /* No conversion happened. Currently this is possible ONLY if the secondary does not support triggers and
+ * all the records are trigger related records (^#t or ZTRIG or ZTWORM). Need to send NULL record instead.
+ */
+ assert(!receiver_supports_triggers);
+ prefix = (jrec_prefix *)(cb);
+ if (V24_NULL_RECLEN > conv_bufsiz)
+ {
+ repl_errno = EREPL_INTLFILTER_NOSPC;
+ status = -1;
+ } else
+ INITIALIZE_V24_NULL_RECORD(prefix, cb, this_upd_seqno, 0); /* Side-effect: cb is incremented */
+ }
}
*conv_len = (uint4)(cb - conv_buff);
assert((0 < *conv_len) || (-1 == status));
@@ -2160,15 +2239,16 @@ int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
return(status);
}
-/* Convert a transaction from jnl version 22/23 (V5.5-000 onwards) to 21 (V5.4-002 through V5.4-002B)
- * For differences between the two versions, see the comment in jnl_v19TOv22. In addition, take care of the following.
- * (a) If the remote side does NOT support triggers, then skip ^#t or ZTWORM or ZTRIG journal records.
+/* Convert a transaction from jnl version V24 (V6.2-000 onwards) to V21 (V5.4-002 through V5.4-002B)
+ * For differences between the two versions, see the comment in jnl_v19TOv24. In addition, take care of the following.
+ * (a) If the remote side does NOT support triggers, then skip ^#t/ZTWORM/ZTRIG/LGTRIG journal records.
* If the entire transaction consists of skipped records, send a NULL record instead.
- * Note: This function (jnl_v21TOv22) is somewhat similar to jnl_v22TOv19 except that ZTRIG records can be seen in v21
+ * (b) If remote side does support triggers, then skip LGTRIG journal records as they are not known to the older journal format.
+ * Note: This function (jnl_v21TOv24) is somewhat similar to jnl_v24TOv19 except that ZTRIG records can be seen in v21
* whereas it cannot be in v19. In addition, no ^#t("GBL","#LABEL") or ^#t("GBL",1,"XECUTE") conversions are needed
- * since the ^#t format is unchanged between V21 and V22.
+ * since the ^#t format is unchanged between V21 and V24.
*/
-int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+int jnl_v24TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
{
unsigned char *jb, *cb, *cstart, *jstart, *mumps_node_ptr;
char *keyend, *ptr;
@@ -2178,7 +2258,7 @@ int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
jrec_prefix *prefix;
seq_num this_upd_seqno;
uint4 trigupd_type = NO_TRIG_JREC;
- boolean_t promote_uupd_to_tupd, receiver_supports_triggers;
+ boolean_t promote_uupd_to_tupd, receiver_supports_triggers, hasht_seen;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -2193,6 +2273,7 @@ int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
* supports triggers is equal to checking whether the REMOTE side supports triggers.
*/
receiver_supports_triggers = REMOTE_TRIGGER_SUPPORT;
+ hasht_seen = FALSE;
while (JREC_PREFIX_SIZE <= jlen)
{
assert(0 == ((UINTPTR_T)jb % SIZEOF(uint4)));
@@ -2208,15 +2289,16 @@ int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(IS_REPLICATED(rectype));
if (IS_TUPD(rectype))
promote_uupd_to_tupd = FALSE;
- if (!receiver_supports_triggers && (IS_ZTRIG(rectype) || IS_ZTWORM(rectype)))
- { /* ZTRIG or $ZTWORMHOLE jnl records cannot be handled by remote side as it does not support triggers so
- * skip converting. If this is a TUPD rectype (actually JRT_TZTWORM/JRT_TZTRIG) then the next UUPD has to
- * be promoted to a TUPD type to account for the balance in TUPD and TCOM records
+ if (IS_LGTRIG(rectype) || (!receiver_supports_triggers && (IS_ZTRIG(rectype) || IS_ZTWORM(rectype))))
+ { /* (i) LGTRIG journal records cannot be handled by remote side (whether or not it supports triggers) OR
+ * (ii) ZTRIG/$ZTWORMHOLE jnl records cannot be handled by remote side as it does not support triggers.
+ * So skip converting in either case. If this is a TUPD rectype (actually JRT_TZTWORM/JRT_TZTRIG) then
+ * the next UUPD has to be promoted to a TUPD type to account for the balance in TUPD and TCOM records.
*/
assert((cb == cstart) && (jb == jstart)); /* No conversions yet */
if (IS_TUPD(rectype))
{
- assert((JRT_TZTWORM == rectype) || (JRT_TZTRIG == rectype));
+ assert((JRT_TZTWORM == rectype) || (JRT_TLGTRIG == rectype) || (JRT_TZTRIG == rectype));
promote_uupd_to_tupd = TRUE;
}
} else
@@ -2229,16 +2311,16 @@ int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(SIZEOF(token_seq_t) == SIZEOF(seq_num));
t_len = (JREC_PREFIX_SIZE + SIZEOF(token_seq_t));
memcpy(cb, jb, t_len);
- ((jrec_prefix *)cb)->forwptr = conv_reclen; /* forwptr will be different between V21 and V22 */
+ ((jrec_prefix *)cb)->forwptr = conv_reclen; /* forwptr will be different between V21 and V24 */
assert((jb + t_len - jstart) == OFFSETOF(struct_jrec_upd, strm_seqno));
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (IS_SET_KILL_ZKILL_ZTWORM_ZTRIG(rectype))
{
assert((cb == cstart) && (jb == jstart));
- /* The ^#t structure is identical between V21 and V22 journal formats so no need to have any
- * code related to that here (like we do in jnl_v22TOv19) except in the case where the
+ /* The ^#t structure is identical between V21 and V24 journal formats so no need to have any
+ * code related to that here (like we do in jnl_v24TOv19) except in the case where the
* secondary side does NOT support triggers.
*/
- GET_JREC_UPD_TYPE(jb + V22_MUMPS_NODE_OFFSET, trigupd_type);
+ GET_JREC_UPD_TYPE(jb + V24_MUMPS_NODE_OFFSET, trigupd_type);
if (receiver_supports_triggers)
{
if (NON_REPLIC_JREC_TRIG == trigupd_type)
@@ -2262,6 +2344,7 @@ int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert((cb == cstart) && (jb == jstart));
jb = jb + reclen;
jlen -= reclen;
+ hasht_seen = TRUE;
continue;
}
/* t_len bytes have already been copied. Skip 8-byte strm_seqno (absent in V21) and copy rest */
@@ -2308,25 +2391,28 @@ int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
}
assert((0 == jlen) || (-1 == status));
assert((jb == (jnl_buff + *jnl_len)) || (-1 == status));
- if ((-1 != status) && (cb == conv_buff))
- { /* No conversion happened. Currently this is possible ONLY if the secondary does not support triggers and
- * all the records are trigger related records (^#t or ZTRIG or ZTWORM). Need to send NULL record instead.
- */
- assert(!receiver_supports_triggers);
+ if (-1 != status)
+ {
GTMTRIG_ONLY(
- if (!(TREF(replgbl)).trig_replic_suspect_seqno)
+ if (hasht_seen && !(TREF(replgbl)).trig_replic_suspect_seqno)
(TREF(replgbl)).trig_replic_suspect_seqno = this_upd_seqno;
)
- prefix = (jrec_prefix *)(cb);
- if (NULL_RECLEN > conv_bufsiz)
- {
- repl_errno = EREPL_INTLFILTER_NOSPC;
- status = -1;
- } else
- { /* Create NULL record. Since the null record format is same for V17 and V21, it is safe to use the
- * below macro. Note: Side-effect: cb is incremented by below macro
+ if (cb == conv_buff)
+ { /* No conversion happened. Currently this is possible ONLY if the secondary does not support triggers and
+ * all the records are trigger related records (^#t/ZTRIG/ZTWORM). Need to send NULL record instead.
*/
- INITIALIZE_V17_NULL_RECORD(prefix, cb, this_upd_seqno);
+ assert(!receiver_supports_triggers);
+ prefix = (jrec_prefix *)(cb);
+ if (NULL_RECLEN > conv_bufsiz)
+ {
+ repl_errno = EREPL_INTLFILTER_NOSPC;
+ status = -1;
+ } else
+ { /* Create NULL record. Since the null record format is same for V17 and V21, it is safe to use the
+ * below macro. Note: Side-effect: cb is incremented by below macro
+ */
+ INITIALIZE_V17_NULL_RECORD(prefix, cb, this_upd_seqno);
+ }
}
}
*conv_len = (uint4)(cb - conv_buff);
@@ -2334,13 +2420,13 @@ int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
return status;
}
-/* Convert a transaction from jnl version 22/23 (V5.5-000 onwards) to 22/23 (V5.5-000 onwards)
- * Same version filters are needed if one of the below is true.
+/* Convert a transaction from jnl version V22/V23 (V5.5-000 thru V6.1-000) to V24 (V6.2-000 onwards).
* (a) If null-subscript collation is different between the primary and the secondary
- * (b) If the remote side does NOT support triggers, then skip ^#t or ZTWORM or ZTRIG journal records & reset nodeflags (if set).
- * If the entire transaction consists of skipped records, send a NULL record instead.
+ * (b) If the remote side does NOT support triggers, then skip ^#t/ZTWORM/ZTRIG journal records & reset nodeflags (if set).
+ * Note that V22 did not support LGTRIG records so dont need to check for them.
+ * (c) If the entire transaction consists of skipped records, send a NULL record instead.
*/
-int jnl_v22TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+int jnl_v22TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
{
unsigned char *jb, *cb, *cstart, *jstart, *ptr, *mumps_node_ptr;
enum jnl_record_type rectype;
@@ -2349,7 +2435,7 @@ int jnl_v22TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
jrec_prefix *prefix;
seq_num this_upd_seqno, this_strm_seqno;
uint4 trigupd_type = NO_TRIG_JREC;
- boolean_t promote_uupd_to_tupd, remote_supports_triggers;
+ boolean_t promote_uupd_to_tupd, receiver_supports_triggers, hasht_seen;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -2359,15 +2445,12 @@ int jnl_v22TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
jlen = *jnl_len;
this_upd_seqno = seq_num_zero;
promote_uupd_to_tupd = FALSE;
- /* The following assert ensures that filtering is initiated by the responsible party and in the expected direction, for the
- * same function can be used for both V23->V22 and V23->V23 replication. In the case of V23->V22 it can be either the source
- * or the receiver doing the filtering, so assert accordingly.
- */
- assert(is_src_server || (LOCAL_JNL_VER > REMOTE_JNL_VER));
- /* Since this filter function will be invoked only on the source side, the check for whether the receiver
- * supports triggers is equal to checking whether the REMOTE side supports triggers.
+ assert(is_rcvr_server);
+ /* Since this filter function will be invoked only on the receiver side, the check for whether the receiver
+ * supports triggers is equal to checking whether the LOCAL side supports triggers.
*/
- remote_supports_triggers = REMOTE_TRIGGER_SUPPORT;
+ receiver_supports_triggers = LOCAL_TRIGGER_SUPPORT;
+ hasht_seen = FALSE;
while (JREC_PREFIX_SIZE <= jlen)
{
assert(0 == ((UINTPTR_T)jb % SIZEOF(uint4)));
@@ -2387,7 +2470,7 @@ int jnl_v22TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert(JRT_MAX_V23 >= rectype);
if (IS_TUPD(rectype))
promote_uupd_to_tupd = FALSE;
- if (!remote_supports_triggers && (IS_ZTRIG(rectype) || IS_ZTWORM(rectype)))
+ if (!receiver_supports_triggers && (IS_ZTRIG(rectype) || IS_ZTWORM(rectype)))
{ /* $ZTWORMHOLE jnl record cannot be handled by secondary which does not support triggers so skip converting.
* If this is a TUPD rectype (actually JRT_TZTWORM/JRT_TZTRIG) then the next UUPD has to be promoted to a
* TUPD type to account for the balance in TUPD and TCOM records
@@ -2402,11 +2485,11 @@ int jnl_v22TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
{
conv_reclen = prefix->forwptr ;
BREAK_IF_NOSPC((cb - conv_buff + conv_reclen), conv_bufsiz, status); /* check for available space */
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (IS_SET_KILL_ZKILL_ZTWORM_ZTRIG(rectype))
{
assert((jb == jstart) && (cb == cstart));
GET_JREC_UPD_TYPE((jb + FIXED_UPD_RECLEN), trigupd_type);
- if (remote_supports_triggers)
+ if (receiver_supports_triggers)
{
if (NON_REPLIC_JREC_TRIG == trigupd_type)
{
@@ -2429,11 +2512,12 @@ int jnl_v22TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
assert((cb == cstart) && (jb == jstart));
jb = jb + reclen;
jlen -= reclen;
+ hasht_seen = TRUE;
continue;
}
memcpy(cb, jb, conv_reclen);
mumps_node_ptr = cb + FIXED_UPD_RECLEN;
- if (!remote_supports_triggers)
+ if (!receiver_supports_triggers)
((jnl_string *)mumps_node_ptr)->nodeflags = 0;
NULLSUBSC_TRANSFORM_IF_NEEDED(mumps_node_ptr);
if (IS_TUPD(rectype))
@@ -2468,24 +2552,354 @@ int jnl_v22TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, ui
jb = jb + reclen;
jlen -= reclen;
}
- assert((0 == jlen) || (-1 == status) || (HASHT_JREC == trigupd_type));
- assert((jb == (jnl_buff + *jnl_len)) || (-1 == status) || (HASHT_JREC == trigupd_type));
- if ((-1 != status) && (cb == conv_buff))
- { /* No conversion happened. Currently this is possible ONLY if the remote side does not support triggers and
- * all the records are trigger related records (^#t or ZTRIG or ZTWORM). Need to send NULL record instead.
- */
- assert(!remote_supports_triggers);
+ assert((0 == jlen) || (-1 == status));
+ assert((jb == (jnl_buff + *jnl_len)) || (-1 == status));
+ if (-1 != status)
+ {
+ GTMTRIG_ONLY(
+ if (hasht_seen && !(TREF(replgbl)).trig_replic_suspect_seqno)
+ (TREF(replgbl)).trig_replic_suspect_seqno = this_upd_seqno;
+ )
+ if (cb == conv_buff)
+ { /* No conversion happened. Currently this is possible ONLY if the receiver side does not support triggers
+ * and all the records are trigger related records (^#t/ZTRIG/ZTWORM). Need to send NULL record instead.
+ */
+ assert(!receiver_supports_triggers);
+ prefix = (jrec_prefix *)(cb);
+ if (NULL_RECLEN > conv_bufsiz)
+ {
+ repl_errno = EREPL_INTLFILTER_NOSPC;
+ status = -1;
+ } else
+ INITIALIZE_V24_NULL_RECORD(prefix, cb, this_upd_seqno, this_strm_seqno); /* Note: cb is updated */
+ }
+ }
+ *conv_len = (uint4)(cb - conv_buff);
+ assert((0 < *conv_len) || (-1 == status));
+ DEBUG_ONLY(
+ if (-1 != status)
+ DBG_CHECK_IF_CONVBUFF_VALID(conv_buff, *conv_len);
+ )
+ return(status);
+}
+
+/* Convert a transaction from jnl version V24 (V6.2-000 onwards) to V22/V23 (V5.5-000 thru V6.1-000).
+ * (a) If null-subscript collation is different between the primary and the secondary
+ * (b) If the remote side does NOT support triggers, then skip ^#t/ZTWORM/ZTRIG journal records & reset nodeflags (if set).
+ * Note that V22 did not support LGTRIG records so dont need to check for them.
+ * (c) If remote side does support triggers, then skip LGTRIG journal records as they are not known to the older journal format.
+ * (d) If the entire transaction consists of skipped records, send a NULL record instead.
+ */
+int jnl_v24TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+{
+ unsigned char *jb, *cb, *cstart, *jstart, *ptr, *mumps_node_ptr;
+ enum jnl_record_type rectype;
+ int status, reclen, conv_reclen;
+ uint4 jlen, tcom_num = 0, tupd_num = 0;
+ jrec_prefix *prefix;
+ seq_num this_upd_seqno, this_strm_seqno;
+ uint4 trigupd_type = NO_TRIG_JREC;
+ boolean_t promote_uupd_to_tupd, receiver_supports_triggers, hasht_seen;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ jb = jnl_buff;
+ cb = conv_buff;
+ status = SS_NORMAL;
+ jlen = *jnl_len;
+ this_upd_seqno = seq_num_zero;
+ promote_uupd_to_tupd = FALSE;
+ assert(is_src_server);
+ /* Since this filter function will be invoked only on the source side, the check for whether the receiver
+ * supports triggers is equal to checking whether the REMOTE side supports triggers.
+ */
+ receiver_supports_triggers = REMOTE_TRIGGER_SUPPORT;
+ hasht_seen = FALSE;
+ while (JREC_PREFIX_SIZE <= jlen)
+ {
+ assert(0 == ((UINTPTR_T)jb % SIZEOF(uint4)));
+ prefix = (jrec_prefix *)jb;
+ rectype = (enum jnl_record_type)prefix->jrec_type;
+ cstart = cb;
+ jstart = jb;
+ reclen = prefix->forwptr;
+ BREAK_IF_BADREC(prefix, status); /* check if we encountered a bad record */
+ BREAK_IF_INCMPLREC(reclen, jlen, status); /* check if this record is incomplete */
+ if (this_upd_seqno == seq_num_zero)
+ {
+ this_upd_seqno = GET_JNL_SEQNO(jb);
+ this_strm_seqno = GET_STRM_SEQNO(jb);
+ }
+ assert(IS_REPLICATED(rectype));
+ assert(JRT_MAX_V24 >= rectype);
+ if (IS_TUPD(rectype))
+ promote_uupd_to_tupd = FALSE;
+ if (IS_LGTRIG(rectype) || (!receiver_supports_triggers && (IS_ZTRIG(rectype) || IS_ZTWORM(rectype))))
+ { /* $ZTWORMHOLE or ZTRIG jnl record cannot be handled by secondary which does not support triggers
+ * AND LGTRIG jnl record cannot be handled even by a secondary that supports triggers so skip converting.
+ * If this is a TUPD rectype (actually JRT_TZTWORM/JRT_TZTRIG) then the next UUPD has to be promoted to a
+ * TUPD type to account for the balance in TUPD and TCOM records
+ */
+ assert((cb == cstart) && (jb == jstart)); /* No conversions yet */
+ if (IS_TUPD(rectype))
+ {
+ assert((JRT_TZTWORM == rectype) || (JRT_TLGTRIG == rectype) || (JRT_TZTRIG == rectype));
+ promote_uupd_to_tupd = TRUE;
+ }
+ } else
+ {
+ conv_reclen = prefix->forwptr ;
+ BREAK_IF_NOSPC((cb - conv_buff + conv_reclen), conv_bufsiz, status); /* check for available space */
+ if (IS_SET_KILL_ZKILL_ZTWORM_ZTRIG(rectype))
+ {
+ assert((jb == jstart) && (cb == cstart));
+ GET_JREC_UPD_TYPE((jb + FIXED_UPD_RECLEN), trigupd_type);
+ if (receiver_supports_triggers)
+ {
+ if (NON_REPLIC_JREC_TRIG == trigupd_type)
+ {
+ if (IS_TUPD(rectype))
+ promote_uupd_to_tupd = TRUE;
+ assert((cb == cstart) && (jb == jstart));
+ jb = jb + reclen;
+ jlen -= reclen;
+ continue;
+ }
+ } else if (HASHT_JREC == trigupd_type)
+ { /* Journal record has a #t global. #t records are not replicated if the secondary does not
+ * support triggers. However, $ZTRIGGER() usages within TP can cause ^#t records to be
+ * generated in the middle of a TP transaction. Hence skip the ^#t records. However, if this
+ * ^#t record is a TUPD record, then note it down so that we promote the next UUPD record to
+ * a TUPD record.
+ */
+ if (IS_TUPD(rectype))
+ promote_uupd_to_tupd = TRUE;
+ assert((cb == cstart) && (jb == jstart));
+ jb = jb + reclen;
+ jlen -= reclen;
+ hasht_seen = TRUE;
+ continue;
+ }
+ memcpy(cb, jb, conv_reclen);
+ mumps_node_ptr = cb + FIXED_UPD_RECLEN;
+ if (!receiver_supports_triggers)
+ ((jnl_string *)mumps_node_ptr)->nodeflags = 0;
+ NULLSUBSC_TRANSFORM_IF_NEEDED(mumps_node_ptr);
+ if (IS_TUPD(rectype))
+ tupd_num++;
+ else if (IS_UUPD(rectype) && promote_uupd_to_tupd)
+ {
+ ((jrec_prefix *)(cb))->jrec_type--;
+ assert(IS_TUPD(((jrec_prefix *)(cb))->jrec_type));
+ promote_uupd_to_tupd = FALSE;
+ tupd_num++;
+ }
+ } else if (JRT_TCOM == rectype)
+ {
+ assert((jb == jstart) && (cb == cstart));
+ tcom_num++;
+ if (tcom_num > tupd_num)
+ {
+ jb = jb + reclen;
+ jlen -= reclen;
+ continue;
+ }
+ memcpy(cb, jb, conv_reclen);
+ ((struct_jrec_tcom *)(cb))->num_participants = tupd_num;
+ } else
+ {
+ assert(JRT_NULL == rectype);
+ assert((cb == cstart) && (jb == jstart));
+ memcpy(cb, jb, conv_reclen);
+ }
+ cb = cb + conv_reclen;
+ }
+ jb = jb + reclen;
+ jlen -= reclen;
+ }
+ assert((0 == jlen) || (-1 == status));
+ assert((jb == (jnl_buff + *jnl_len)) || (-1 == status));
+ if (-1 != status)
+ {
GTMTRIG_ONLY(
- if (!(TREF(replgbl)).trig_replic_suspect_seqno)
+ if (hasht_seen && !(TREF(replgbl)).trig_replic_suspect_seqno)
(TREF(replgbl)).trig_replic_suspect_seqno = this_upd_seqno;
)
- prefix = (jrec_prefix *)(cb);
- if (NULL_RECLEN > conv_bufsiz)
+ if (cb == conv_buff)
+ { /* No conversion happened. Currently this is possible ONLY if the receiver side does not support triggers
+ * and all the records are trigger related records (^#t/ZTRIG/ZTWORM/LGTRIG).
+ * Need to send NULL record instead.
+ */
+ assert(!receiver_supports_triggers);
+ prefix = (jrec_prefix *)(cb);
+ if (NULL_RECLEN > conv_bufsiz)
+ {
+ repl_errno = EREPL_INTLFILTER_NOSPC;
+ status = -1;
+ } else
+ INITIALIZE_V24_NULL_RECORD(prefix, cb, this_upd_seqno, this_strm_seqno); /* Note : cb is updated */
+ }
+ }
+ *conv_len = (uint4)(cb - conv_buff);
+ assert((0 < *conv_len) || (-1 == status));
+ DEBUG_ONLY(
+ if (-1 != status)
+ DBG_CHECK_IF_CONVBUFF_VALID(conv_buff, *conv_len);
+ )
+ return(status);
+}
+
+/* Convert a transaction from jnl version V24 (V6.2-000 onwards) to V24 (V6.2-000 onwards).
+ * Same version filters are needed if one of the below is true.
+ * (a) If null-subscript collation is different between the primary and the secondary
+ * (b) If the remote side does NOT support triggers, then skip ^#t/ZTWORM/LGTRIG/ZTRIG journal records & reset nodeflags (if set).
+ * (c) If the remote side does support triggers, then skip ^#t journal records (physical records). Instead send just the
+ * preceding LGTRIG record (logical record).
+ * (d) If the entire transaction consists of skipped records, send a NULL record instead.
+ */
+int jnl_v24TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz)
+{
+ unsigned char *jb, *cb, *cstart, *jstart, *ptr, *mumps_node_ptr;
+ enum jnl_record_type rectype;
+ int status, reclen, conv_reclen;
+ uint4 jlen, tcom_num = 0, tupd_num = 0;
+ jrec_prefix *prefix;
+ seq_num this_upd_seqno, this_strm_seqno;
+ uint4 trigupd_type = NO_TRIG_JREC;
+ boolean_t promote_uupd_to_tupd, receiver_supports_triggers;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ jb = jnl_buff;
+ cb = conv_buff;
+ status = SS_NORMAL;
+ jlen = *jnl_len;
+ this_upd_seqno = seq_num_zero;
+ promote_uupd_to_tupd = FALSE;
+ /* The following assert ensures that filtering is initiated by the responsible party and in the expected direction. */
+ assert(is_src_server);
+ /* Since this filter function will be invoked only on the source side, the check for whether the receiver
+ * supports triggers is equal to checking whether the REMOTE side supports triggers.
+ */
+ receiver_supports_triggers = REMOTE_TRIGGER_SUPPORT;
+ GTMTRIG_ONLY(assert(receiver_supports_triggers);) /* if receiver is V24 format, it should have been built
+ * with trigger support enabled since we dont either build
+ * anymore OR replicate anymore to trigger unsupported platforms
+ * (HPPA/Tru64/VMS) from trigger-supporting Unix platforms.
+ */
+ while (JREC_PREFIX_SIZE <= jlen)
+ {
+ assert(0 == ((UINTPTR_T)jb % SIZEOF(uint4)));
+ prefix = (jrec_prefix *)jb;
+ rectype = (enum jnl_record_type)prefix->jrec_type;
+ cstart = cb;
+ jstart = jb;
+ reclen = prefix->forwptr;
+ BREAK_IF_BADREC(prefix, status); /* check if we encountered a bad record */
+ BREAK_IF_INCMPLREC(reclen, jlen, status); /* check if this record is incomplete */
+ if (this_upd_seqno == seq_num_zero)
{
- repl_errno = EREPL_INTLFILTER_NOSPC;
- status = -1;
+ this_upd_seqno = GET_JNL_SEQNO(jb);
+ this_strm_seqno = GET_STRM_SEQNO(jb);
+ }
+ assert(IS_REPLICATED(rectype));
+ assert(JRT_MAX_V24 >= rectype);
+ if (IS_TUPD(rectype))
+ promote_uupd_to_tupd = FALSE;
+ if (!receiver_supports_triggers && (IS_ZTRIG(rectype) || IS_ZTWORM(rectype) || IS_LGTRIG(rectype)))
+ { /* $ZTWORMHOLE or ZTRIG or LGTRIG jnl records cannot be handled by secondary which does not
+ * support triggers so skip converting. If this is a TUPD rectype (actually JRT_TZTWORM/JRT_TZTRIG)
+ * then the next UUPD has to be promoted to a TUPD type to account for the balance in TUPD/TCOM records.
+ */
+ assert((cb == cstart) && (jb == jstart)); /* No conversions yet */
+ if (IS_TUPD(rectype))
+ {
+ assert((JRT_TZTWORM == rectype) || (JRT_TLGTRIG == rectype) || (JRT_TZTRIG == rectype));
+ promote_uupd_to_tupd = TRUE;
+ }
} else
- INITIALIZE_V22_NULL_RECORD(prefix, cb, this_upd_seqno, this_strm_seqno); /* Side-effect: cb is updated */
+ {
+ conv_reclen = prefix->forwptr ;
+ BREAK_IF_NOSPC((cb - conv_buff + conv_reclen), conv_bufsiz, status); /* check for available space */
+ if (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype))
+ {
+ assert((jb == jstart) && (cb == cstart));
+ GET_JREC_UPD_TYPE((jb + FIXED_UPD_RECLEN), trigupd_type);
+ if (HASHT_JREC == trigupd_type)
+ { /* Journal record has a #t global. #t records are not replicated irrespective of whether
+ * the secondary support triggers or not. Hence skip them. However, if this ^#t record is
+ * a TUPD record, then note it down so that we promote the next UUPD record to a TUPD.
+ */
+ if (IS_TUPD(rectype))
+ promote_uupd_to_tupd = TRUE;
+ assert((cb == cstart) && (jb == jstart));
+ jb = jb + reclen;
+ jlen -= reclen;
+ continue;
+ }
+ if (receiver_supports_triggers && (NON_REPLIC_JREC_TRIG == trigupd_type))
+ {
+ if (IS_TUPD(rectype))
+ promote_uupd_to_tupd = TRUE;
+ assert((cb == cstart) && (jb == jstart));
+ jb = jb + reclen;
+ jlen -= reclen;
+ continue;
+ }
+ memcpy(cb, jb, conv_reclen);
+ mumps_node_ptr = cb + FIXED_UPD_RECLEN;
+ if (!receiver_supports_triggers)
+ ((jnl_string *)mumps_node_ptr)->nodeflags = 0;
+ NULLSUBSC_TRANSFORM_IF_NEEDED(mumps_node_ptr);
+ if (IS_TUPD(rectype))
+ tupd_num++;
+ else if (IS_UUPD(rectype) && promote_uupd_to_tupd)
+ {
+ ((jrec_prefix *)(cb))->jrec_type--;
+ assert(IS_TUPD(((jrec_prefix *)(cb))->jrec_type));
+ promote_uupd_to_tupd = FALSE;
+ tupd_num++;
+ }
+ } else if (JRT_TCOM == rectype)
+ {
+ assert((jb == jstart) && (cb == cstart));
+ tcom_num++;
+ if (tcom_num > tupd_num)
+ {
+ jb = jb + reclen;
+ jlen -= reclen;
+ continue;
+ }
+ memcpy(cb, jb, conv_reclen);
+ ((struct_jrec_tcom *)(cb))->num_participants = tupd_num;
+ } else
+ {
+ assert(JRT_NULL == rectype);
+ assert((cb == cstart) && (jb == jstart));
+ memcpy(cb, jb, conv_reclen);
+ }
+ cb = cb + conv_reclen;
+ }
+ jb = jb + reclen;
+ jlen -= reclen;
+ }
+ assert((0 == jlen) || (-1 == status));
+ assert((jb == (jnl_buff + *jnl_len)) || (-1 == status));
+ if (-1 != status)
+ {
+ if (cb == conv_buff)
+ { /* No conversion happened. Currently this is possible ONLY if the remote side does not support triggers and
+ * all the records are trigger related records (LGTRIG/ZTRIG/ZTWORM). Need to send NULL record instead.
+ */
+ assert(!receiver_supports_triggers);
+ prefix = (jrec_prefix *)(cb);
+ if (NULL_RECLEN > conv_bufsiz)
+ {
+ repl_errno = EREPL_INTLFILTER_NOSPC;
+ status = -1;
+ } else
+ INITIALIZE_V24_NULL_RECORD(prefix, cb, this_upd_seqno, this_strm_seqno); /* Note: cb is updated */
+ }
}
*conv_len = (uint4)(cb - conv_buff);
assert((0 < *conv_len) || (-1 == status));
diff --git a/sr_port/repl_filter.h b/sr_port/repl_filter.h
index d0be232..2d80eda 100644
--- a/sr_port/repl_filter.h
+++ b/sr_port/repl_filter.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,13 +19,19 @@
#define FILTERSTART_ERR -1
#define FILTER_CMD_ARG_DELIM_TOKENS " \t"
+/* Define the maximum jnl extract byte length of ONE line of journal extract.
+ * Note that for a TP transaction that has N updates, the journal extract length needed at most is N times this value.
+ */
#ifdef UNIX
-# define MAX_EXTRACT_BUFSIZ 10 * MAX_LOGI_JNL_REC_SIZE /* Since we might need up to 9X + 11
- * of MAX_LOGI_JNL_REC_SIZE */
+# define MAX_ONE_JREC_EXTRACT_BUFSIZ 10 * MAX_LOGI_JNL_REC_SIZE /* Since we might need up to 9X + 11
+ * of MAX_LOGI_JNL_REC_SIZE */
#else
-# define MAX_EXTRACT_BUFSIZ 1 * 1024 * 1024
+# define MAX_ONE_JREC_EXTRACT_BUFSIZ 1 * 1024 * 1024
#endif
+#define JNL2EXTCVT_EXPAND_FACTOR 2 /* # of max-sized journal records by which jnl2extcvt expands buffer if not enough */
+#define EXT2JNLCVT_EXPAND_FACTOR 8 /* # of max-sized journal records by which ext2jnlcvt expands buffer if not enough */
+
#define NO_FILTER 0
#define INTERNAL_FILTER 0x00000001
#define EXTERNAL_FILTER 0x00000002
@@ -62,6 +68,7 @@ typedef int (*intlfltr_t)(uchar_ptr_t, uint4 *, uchar_ptr_t, uint4 *, uint4);
* V21 V21 GT.M V5.4-002 Added replicated ZTRIGGER jnl record type
* V22 V22 GT.M V5.5-000 strm_seqno added to all logical records (supplementary instances)
* V22 V23 GT.M V6.0-000 Various journaling-related limits have changed, allowing for much larger journal records
+ * V24 V24 GT.M V6.2-000 New logical trigger journal record (TLGTRIG and ULGTRIG jnl records)
*/
typedef enum
@@ -71,6 +78,7 @@ typedef enum
REPL_FILTER_V19, /* filter version corresponding to journal format V19 */
REPL_FILTER_V21, /* filter version corresponding to journal format V21 */
REPL_FILTER_V22, /* filter version corresponding to journal format V22 */
+ REPL_FILTER_V24, /* filter version corresponding to journal format V24 */
REPL_FILTER_MAX
} repl_filter_t;
@@ -83,26 +91,31 @@ typedef enum
REPL_JNL_V21, /* enum corresponding to journal format V21 */
REPL_JNL_V22, /* enum corresponding to journal format V22 */
REPL_JNL_V23, /* enum corresponding to journal format V23 */
+ REPL_JNL_V24, /* enum corresponding to journal format V24 */
REPL_JNL_MAX
} repl_jnl_t;
#define IF_INVALID ((intlfltr_t)0L)
#define IF_NONE ((intlfltr_t)(-1L))
-#define IF_22TO17 (intlfltr_t)jnl_v22TOv17
-#define IF_22TO19 (intlfltr_t)jnl_v22TOv19
-#define IF_22TO21 (intlfltr_t)jnl_v22TOv21
-#define IF_17TO22 (intlfltr_t)jnl_v17TOv22
-#define IF_19TO22 (intlfltr_t)jnl_v19TOv22
-#define IF_21TO22 (intlfltr_t)jnl_v21TOv22
-#define IF_22TO22 (intlfltr_t)jnl_v22TOv22
+#define IF_24TO17 (intlfltr_t)jnl_v24TOv17
+#define IF_24TO19 (intlfltr_t)jnl_v24TOv19
+#define IF_24TO21 (intlfltr_t)jnl_v24TOv21
+#define IF_24TO22 (intlfltr_t)jnl_v24TOv22
+#define IF_17TO24 (intlfltr_t)jnl_v17TOv24
+#define IF_19TO24 (intlfltr_t)jnl_v19TOv24
+#define IF_21TO24 (intlfltr_t)jnl_v21TOv24
+#define IF_22TO24 (intlfltr_t)jnl_v22TOv24
+#define IF_24TO24 (intlfltr_t)jnl_v24TOv24
-extern int jnl_v22TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
-extern int jnl_v17TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
-extern int jnl_v22TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
-extern int jnl_v19TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
-extern int jnl_v22TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
-extern int jnl_v21TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
-extern int jnl_v22TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v24TOv17(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v17TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v24TOv19(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v19TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v24TOv21(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v21TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v24TOv22(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v22TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
+extern int jnl_v24TOv24(uchar_ptr_t jnl_buff, uint4 *jnl_len, uchar_ptr_t conv_buff, uint4 *conv_len, uint4 conv_bufsiz);
extern void repl_check_jnlver_compat(UNIX_ONLY(boolean_t same_endianness));
@@ -142,18 +155,20 @@ GBLREF intlfltr_t repl_filter_cur2old[JNL_VER_THIS - JNL_VER_EARLIEST_REPL + 1];
#define V21_JNL_VER 21
#define V22_JNL_VER 22
#define V23_JNL_VER 23
+#define V24_JNL_VER 24
#define V17_NULL_RECLEN 40 /* size of a JRT_NULL record in V17/V18 jnl format */
#define V19_NULL_RECLEN 40 /* size of a JRT_NULL record in V19/V20 jnl format */
#define V21_NULL_RECLEN 40 /* size of a JRT_NULL record in V21 jnl format */
#define V22_NULL_RECLEN 48 /* size of a JRT_NULL record in V22/V23 jnl format */
+#define V24_NULL_RECLEN 48 /* size of a JRT_NULL record in V24 jnl format */
#define V19_UPDATE_NUM_OFFSET 32 /* offset of "update_num" member in struct_jrec_upd structure in V19 jnl format */
#define V19_MUMPS_NODE_OFFSET 40 /* offset of "mumps_node" member in struct_jrec_upd structure in V19 jnl format */
#define V19_TCOM_FILLER_SHORT_OFFSET 32 /* offset of "filler_short" in struct_jrec_tcom structure in V19 jnl format */
#define V19_NULL_FILLER_OFFSET 32 /* offset of "filler" in struct_jrec_nullstructure in V19 jnl format */
-#define V22_MUMPS_NODE_OFFSET 48 /* offset of "mumps_node" member in struct_jrec_upd struct in V22/V23 jnl format */
+#define V24_MUMPS_NODE_OFFSET 48 /* offset of "mumps_node" member in struct_jrec_upd struct in V24 jnl format */
typedef struct
{
@@ -165,7 +180,9 @@ typedef struct
} v15_jrec_prefix; /* 16-byte */
int repl_filter_init(char *filter_cmd);
-int repl_filter(seq_num tr_num, unsigned char *tr, int *tr_len, int bufsize);
+int repl_filter(seq_num tr_num, unsigned char **tr, int *tr_len, int *tr_bufsize);
+STATICFNDCL int repl_filter_recv(seq_num tr_num, unsigned char **tr, int *tr_len, int *tr_bufsize, boolean_t send_done);
+STATICFNDCL int repl_filter_recv_line(char *line, int *line_len, int max_line_len, boolean_t send_done);
int repl_stop_filter(void);
void repl_filter_error(seq_num filter_seqno, int why);
@@ -191,6 +208,7 @@ void repl_filter_error(seq_num filter_seqno, int why);
#define APPLY_EXT_FILTER_IF_NEEDED(GTMSOURCE_FILTER, GTMSOURCE_MSGP, DATA_LEN, TOT_TR_LEN) \
{ \
seq_num filter_seqno; \
+ unsigned char *tr; \
\
if (GTMSOURCE_FILTER & EXTERNAL_FILTER) \
{ \
@@ -202,13 +220,14 @@ void repl_filter_error(seq_num filter_seqno, int why);
* according to the update_num. V19 is the first journal filter format which introduced the notion of \
* update_num. \
*/ \
+ tr = GTMSOURCE_MSGP->msg; \
if (V19_JNL_VER <= LOCAL_JNL_VER) \
{ \
- repl_sort_tr_buff(GTMSOURCE_MSGP->msg, DATA_LEN); \
- DBG_VERIFY_TR_BUFF_SORTED(GTMSOURCE_MSGP->msg, DATA_LEN); \
+ repl_sort_tr_buff(tr, DATA_LEN); \
+ DBG_VERIFY_TR_BUFF_SORTED(tr, DATA_LEN); \
} \
- filter_seqno = ((struct_jrec_null *)(GTMSOURCE_MSGP->msg))->jnl_seqno; \
- if (SS_NORMAL != (status = repl_filter(filter_seqno, GTMSOURCE_MSGP->msg, &DATA_LEN, gtmsource_msgbufsiz))) \
+ filter_seqno = ((struct_jrec_null *)tr)->jnl_seqno; \
+ if (SS_NORMAL != (status = repl_filter(filter_seqno, &tr, &DATA_LEN, >msource_msgbufsiz))) \
repl_filter_error(filter_seqno, status); \
TOT_TR_LEN = DATA_LEN + REPL_MSG_HDRLEN; \
} \
@@ -234,28 +253,28 @@ void repl_filter_error(seq_num filter_seqno, int why);
}
#ifdef UNIX
-# define INT_FILTER_RTS_ERROR(FILTER_SEQNO) \
-{ \
- if (EREPL_INTLFILTER_BADREC == repl_errno) \
- rts_error(VARLSTCNT(1) ERR_REPLRECFMT); \
- else if (EREPL_INTLFILTER_REPLGBL2LONG == repl_errno) \
- rts_error(VARLSTCNT(1) ERR_REPLGBL2LONG); \
- else if (EREPL_INTLFILTER_SECNODZTRIGINTP == repl_errno) \
- rts_error(VARLSTCNT(3) ERR_SECNODZTRIGINTP, 1, &FILTER_SEQNO); \
- else if (EREPL_INTLFILTER_MULTILINEXECUTE == repl_errno) \
- rts_error(VARLSTCNT(3) ERR_REPLNOMULTILINETRG, 1, &FILTER_SEQNO); \
- else /* (EREPL_INTLFILTER_INCMPLREC == repl_errno) */ \
- assertpro(FALSE); \
+# define INT_FILTER_RTS_ERROR(FILTER_SEQNO) \
+{ \
+ if (EREPL_INTLFILTER_BADREC == repl_errno) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_REPLRECFMT); \
+ else if (EREPL_INTLFILTER_REPLGBL2LONG == repl_errno) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_REPLGBL2LONG); \
+ else if (EREPL_INTLFILTER_SECNODZTRIGINTP == repl_errno) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SECNODZTRIGINTP, 1, &FILTER_SEQNO); \
+ else if (EREPL_INTLFILTER_MULTILINEXECUTE == repl_errno) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_REPLNOMULTILINETRG, 1, &FILTER_SEQNO); \
+ else /* (EREPL_INTLFILTER_INCMPLREC == repl_errno) */ \
+ assertpro(FALSE); \
}
#else
-# define INT_FILTER_RTS_ERROR(FILTER_SEQNO) \
-{ \
- if (EREPL_INTLFILTER_BADREC == repl_errno) \
- rts_error(VARLSTCNT(1) ERR_REPLRECFMT); \
- else if (EREPL_INTLFILTER_REPLGBL2LONG == repl_errno) \
- rts_error(VARLSTCNT(1) ERR_REPLGBL2LONG); \
- else /* (EREPL_INTLFILTER_INCMPLREC == repl_errno) */ \
- assertpro(FALSE); \
+# define INT_FILTER_RTS_ERROR(FILTER_SEQNO) \
+{ \
+ if (EREPL_INTLFILTER_BADREC == repl_errno) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_REPLRECFMT); \
+ else if (EREPL_INTLFILTER_REPLGBL2LONG == repl_errno) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_REPLGBL2LONG); \
+ else /* (EREPL_INTLFILTER_INCMPLREC == repl_errno) */ \
+ assertpro(FALSE); \
}
#endif
#endif
diff --git a/sr_port/repl_sort_tr_buff.c b/sr_port/repl_sort_tr_buff.c
index 3c3aa4d..657b299 100644
--- a/sr_port/repl_sort_tr_buff.c
+++ b/sr_port/repl_sort_tr_buff.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,7 +24,7 @@
void repl_sort_tr_buff(uchar_ptr_t tr_buff, uint4 tr_bufflen)
{
- boolean_t already_sorted, is_set_kill_zkill_ztrig_ztworm, sorting_needed;
+ boolean_t already_sorted, is_set_kill_zkill_ztworm_lgtrig_ztrig, sorting_needed;
uchar_ptr_t tb, dst_addr, this_jrec_addr, working_record_addr, next_record_addr, reg_top;
static uchar_ptr_t private_tr_buff;
static reg_jrec_info_t *reg_jrec_info_array;
@@ -98,12 +98,13 @@ void repl_sort_tr_buff(uchar_ptr_t tr_buff, uint4 tr_bufflen)
assert(FALSE);
return;
}
- is_set_kill_zkill_ztrig_ztworm = IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype);
+ is_set_kill_zkill_ztworm_lgtrig_ztrig = IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype);
assert(IS_REPLICATED(rectype));
- assert(is_set_kill_zkill_ztrig_ztworm || (JRT_TCOM == rectype));
- if (is_set_kill_zkill_ztrig_ztworm)
+ assert(is_set_kill_zkill_ztworm_lgtrig_ztrig || (JRT_TCOM == rectype));
+ if (is_set_kill_zkill_ztworm_lgtrig_ztrig)
{
assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
+ assert(&rec->jrec_set_kill.update_num == &rec->jrec_lgtrig.update_num);
cur_updnum = rec->jrec_set_kill.update_num;
already_sorted = (already_sorted && (prev_updnum <= cur_updnum));
max_updnum = MAX(max_updnum, cur_updnum);
@@ -186,9 +187,11 @@ void repl_sort_tr_buff(uchar_ptr_t tr_buff, uint4 tr_bufflen)
/* Extract the update_num of the current record */
this_jrec_addr = (private_tr_buff + reg_jrec_info_array[reg_idx].working_offset);
prefix = (jrec_prefix *)(this_jrec_addr);
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(prefix->jrec_type));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(prefix->jrec_type));
assert(SIZEOF(struct_jrec_upd) == SIZEOF(struct_jrec_ztworm));
+ assert(SIZEOF(struct_jrec_upd) == SIZEOF(struct_jrec_lgtrig));
assert(OFFSETOF(struct_jrec_upd, update_num) == OFFSETOF(struct_jrec_ztworm, update_num));
+ assert(OFFSETOF(struct_jrec_upd, update_num) == OFFSETOF(struct_jrec_lgtrig, update_num));
this_reg_updnum = ((struct_jrec_upd *)(this_jrec_addr))->update_num;
assert(this_reg_updnum < (max_updnum + 1));
assert(min_val != this_reg_updnum);
diff --git a/sr_port/replic_gbldefs.c b/sr_port/replic_gbldefs.c
index d2d0472..dc6b474 100644
--- a/sr_port/replic_gbldefs.c
+++ b/sr_port/replic_gbldefs.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2013 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -47,7 +47,9 @@ GBLDEF int repl_filter_bufsiz = 0;
GBLDEF unsigned int jnl_source_datalen, jnl_dest_maxdatalen;
GBLDEF unsigned char jnl_source_rectype, jnl_dest_maxrectype;
GBLDEF char *ext_stop;
+#ifdef DEBUG
GBLDEF char *jb_stop;
+#endif
GBLDEF seq_num lastlog_seqno;
GBLDEF qw_num trans_sent_cnt, last_log_tr_sent_cnt, trans_recvd_cnt, last_log_tr_recvd_cnt;
GBLDEF upd_helper_entry_ptr_t helper_entry;
diff --git a/sr_port/resolve_ref.c b/sr_port/resolve_ref.c
index c0ee025..b7b69d9 100644
--- a/sr_port/resolve_ref.c
+++ b/sr_port/resolve_ref.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -23,24 +23,25 @@
#include "gtmdbglvl.h"
GBLREF boolean_t run_time;
-GBLREF triple t_orig;
-GBLREF mlabel *mlabtab;
GBLREF command_qualifier cmd_qlf;
+GBLREF mlabel *mlabtab;
+GBLREF triple t_orig;
GBLREF uint4 gtmDebugLevel;
+error_def(ERR_ACTLSTTOOLONG);
+error_def(ERR_FMLLSTMISSING);
error_def(ERR_LABELMISSING);
+error_def(ERR_LABELNOTFND);
error_def(ERR_LABELUNKNOWN);
-error_def(ERR_FMLLSTMISSING);
-error_def(ERR_ACTLSTTOOLONG);
int resolve_ref(int errknt)
{
- triple *curtrip, *tripref, *chktrip, *ref, *y;
- tbp *tripbp;
+ int actcnt;
mline *mxl;
mlabel *mlbx;
- oprtype *opnd, *j, *k;
- int actcnt;
+ oprtype *j, *k, *opnd;
+ tbp *tripbp;
+ triple *chktrip, *curtrip, *ref, *tripref, *y;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -165,7 +166,8 @@ int resolve_ref(int errknt)
stx_error(ERR_LABELMISSING, 2, mlbx->mvname.len, mlbx->mvname.addr);
TREF(source_error_found) = 0;
tripref = newtriple(OC_RTERROR);
- tripref->operand[0] = put_ilit(ERR_LABELUNKNOWN);
+ tripref->operand[0] = put_ilit(OC_JMP == curtrip->opcode
+ ? ERR_LABELNOTFND : ERR_LABELUNKNOWN); /* special error for GOTO jmp */
/* This is a subroutine/func reference */
tripref->operand[1] = put_ilit(TRUE);
opnd->oprval.tref = tripref;
@@ -255,7 +257,7 @@ int resolve_ref(int errknt)
/* If for example there are nested $SELECT routines feeding a value to a SET $PIECE/$EXTRACT, this nested checking is
* necessary to make sure no OC_PASSTHRUs remain in the parameter chain to get turned into OC_NOOPs that will
- * cause GTMASSERTs in emit_code.
+ * cause assertpro in emit_code.
*/
void resolve_tref(triple *curtrip, oprtype *opnd)
{
diff --git a/sr_port/rwformat.c b/sr_port/rwformat.c
index 54357bf..3c1a062 100644
--- a/sr_port/rwformat.c
+++ b/sr_port/rwformat.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,6 +19,7 @@
error_def(ERR_COMMAORRPAREXP);
error_def(ERR_CTLMNEXPECTED);
+error_def(ERR_NAMEEXPECTED);
error_def(ERR_RWFORMAT);
int rwformat(void)
@@ -79,7 +80,21 @@ int rwformat(void)
advancewindow();
for (;;)
{
- if (EXPR_FAIL == expr(&x, MUMPS_EXPR))
+ if ((TK_COMMA == TREF(window_token)) || ((n > 1) && TK_RPAREN == TREF(window_token)))
+ { /* language extension - allow empty expr */
+ ref = newtriple(OC_NULLEXP);
+ x = put_tref(ref);
+ } else if (TK_PERIOD == TREF(window_token))
+ { /* language extension - allow pass-by-reference */
+ advancewindow();
+ if (TK_IDENT != TREF(window_token))
+ {
+ stx_error(ERR_NAMEEXPECTED);
+ return FALSE;
+ }
+ x = put_mvar(&(TREF(window_ident)));
+ advancewindow();
+ } else if (EXPR_FAIL == expr(&x, MUMPS_EXPR))
return FALSE;
n++;
ref = newtriple(OC_PARAMETER);
diff --git a/sr_port/secshr_db_clnup.c b/sr_port/secshr_db_clnup.c
index ae1613b..571a1e5 100644
--- a/sr_port/secshr_db_clnup.c
+++ b/sr_port/secshr_db_clnup.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -134,7 +134,7 @@
{ /* "wcblocked" is relevant only if X is the database crit semaphore. In this case, BEFORE salvaging crit, \
* (but AFTER ensuring the previous holder pid is dead) we need to set cnl->wc_blocked to TRUE to \
* ensure whoever grabs crit next does a cache-recovery. This is necessary in case previous holder of crit \
- * had set some cr->in_cw_set to a non-zero value. Not doing cache recovery could cause incorrect GTMASSERTs \
+ * had set some cr->in_cw_set to a non-zero value. Not doing cache recovery could cause incorrect assertpro()s \
* in PIN_CACHE_RECORD macro in t_end/tp_tend. \
*/ \
uint4 pid; \
@@ -628,14 +628,12 @@ void secshr_db_clnup(enum secshr_db_state secshr_state)
/* else is the case where we had a duplicate set that did not update any cw-set */
assert(!tp_update_underway);
assert(non_tp_update_underway); /* should have already determined update is underway */
- if (!non_tp_update_underway)
- { /* This is a situation where we are in non-TP and have a region that we hold
- * crit in and are in the midst of commit but this region was not the current
- * region when we entered secshr_db_clnup. This is an out-of-design situation
- * that we want to catch in Unix (not VMS because it runs in kernel mode).
- */
- UNIX_ONLY(GTMASSERT;) /* in Unix we want to catch this situation even in pro */
- }
+ /* This is a situation where we are in non-TP and have a region that we hold
+ * crit in and are in the midst of commit but this region was not the current
+ * region when we entered secshr_db_clnup. This is an out-of-design situation
+ * that we want to catch in Unix (not VMS because it runs in kernel mode).
+ */
+ UNIX_ONLY(assertpro(non_tp_update_underway));
non_tp_update_underway = TRUE; /* just in case */
update_underway = TRUE; /* just in case */
}
@@ -1106,10 +1104,13 @@ void secshr_db_clnup(enum secshr_db_state secshr_state)
if (SNAPSHOTS_IN_PROG(csa))
{
lcl_ss_ctx = SS_CTX_CAST(csa->ss_ctx);
- assert(NULL != snapshot_cr);
- assert((snapshot_cr == cr) || (snapshot_cr == cr_alt));
- WRITE_SNAPSHOT_BLOCK(csa, snapshot_cr, NULL, snapshot_cr->blk,
- lcl_ss_ctx);
+ if (snapshot_cr->blk < lcl_ss_ctx->total_blks)
+ {
+ assert(NULL != snapshot_cr);
+ assert((snapshot_cr == cr) || (snapshot_cr == cr_alt));
+ WRITE_SNAPSHOT_BLOCK(csa, snapshot_cr, NULL,
+ snapshot_cr->blk, lcl_ss_ctx);
+ }
}
# endif
}
@@ -1617,8 +1618,10 @@ void secshr_db_clnup(enum secshr_db_state secshr_state)
if (dlr_tlevel || (NULL != firstsgminfo))
{
si = csa->sgm_info_ptr;
+ /* Note that it is possible "si" is NULL in case of a GTM-E-MEMORY error in gvcst_init.
+ * Handle that accordingly in the code below.
+ */
kip_csa_usable = (GTM_PROBE(SIZEOF(sgm_info), si, WRITE)) ? TRUE : FALSE;
- assert(kip_csa_usable);
/* Since the kill process cannot be completed, we need to decerement KIP count
* and increment the abandoned_kills count.
*/
@@ -1628,7 +1631,7 @@ void secshr_db_clnup(enum secshr_db_state secshr_state)
PROBE_DECR_KIP(csd, csa, si->kip_csa);
PROBE_INCR_ABANDONED_KILLS(csd, csa);
} else
- assert((NULL == si->kill_set_head) || (NULL == si->kip_csa));
+ assert((NULL == si) || (NULL == si->kill_set_head) || (NULL == si->kip_csa));
} else if (!dlr_tlevel)
{
kip_csa_usable =
@@ -1737,7 +1740,9 @@ void secshr_db_clnup(enum secshr_db_state secshr_state)
{ /* there can be at most one region in non-TP with different curr_tn and early_tn */
assert(!non_tp_update_underway || first_time);
/* for normal termination we should not have been in the midst of commit */
- assert((NORMAL_TERMINATION != secshr_state) || WBTEST_ENABLED(WBTEST_SLEEP_IN_WCS_WTSTART));
+ assert((NORMAL_TERMINATION != secshr_state)
+ || WBTEST_ENABLED(WBTEST_JNL_CREATE_FAIL)
+ || WBTEST_ENABLED(WBTEST_SLEEP_IN_WCS_WTSTART));
DEBUG_ONLY(first_time = FALSE;)
if (update_underway)
{
diff --git a/sr_port/start_for_fetches.c b/sr_port/start_for_fetches.c
index 931e956..947efc1 100644
--- a/sr_port/start_for_fetches.c
+++ b/sr_port/start_for_fetches.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,27 +13,33 @@
#include "compiler.h"
#include "opcode.h"
-GBLREF triple *curr_fetch_trip, *curr_fetch_opr;
GBLREF int4 curr_fetch_count;
-GBLREF mvax *mvaxtab,*mvaxtab_end;
+GBLREF mvax *mvaxtab;
+GBLREF triple *curr_fetch_opr, *curr_fetch_trip;
-void start_for_fetches (void)
+/* When in the body of a FOR loop, we need to maintain the binding for the control variable.
+ * If the action of a command (or function) can alter the symbol table, e.g. BREAK or NEW,
+ * it should call this routine in preference to start_fetches when it detects that it's in the
+ * body of a FOR. While start_fetches just starts a new fetch, this copies the arguments of the prior
+ * fetch to the new fetch because there's no good way to tell which one is for the control variable
+ */
+void start_for_fetches(void)
{
- triple *ref1, *ref2, *fetch_trip;
- int fetch_count, index, idiff;
+ triple *fetch_trip, *ref1, *ref2;
+ int fetch_count, idiff, index;
mvax *idx;
fetch_trip = curr_fetch_trip;
fetch_count = curr_fetch_count;
- start_fetches (OC_FETCH);
+ start_fetches(OC_FETCH);
ref1 = fetch_trip;
ref2 = curr_fetch_trip;
idx = mvaxtab;
while (ref1->operand[1].oprclass)
{
- assert (ref1->operand[1].oprclass == TRIP_REF);
+ assert(ref1->operand[1].oprclass == TRIP_REF);
ref1 = ref1->operand[1].oprval.tref;
- assert (ref1->opcode == OC_PARAMETER);
+ assert(ref1->opcode == OC_PARAMETER);
ref2->operand[1] = put_tref (newtriple (OC_PARAMETER));
ref2 = ref2->operand[1].oprval.tref;
ref2->operand[0] = ref1->operand[0];
@@ -45,18 +51,17 @@ void start_for_fetches (void)
{
if (idiff < 0)
{
- assert (idx->last);
+ assert(idx->last);
idx = idx->last;
idiff++;
- }
- else
+ } else
{
- assert (idx->next);
+ assert(idx->next);
idx = idx->next;
idiff--;
}
}
- assert (idx->mvidx == index);
+ assert(idx->mvidx == index);
idx->var->last_fetch = curr_fetch_trip;
}
curr_fetch_count = fetch_count;
diff --git a/sr_port/stp_gcol_ch.c b/sr_port/stp_gcol_ch.c
index 539d040..7476f90 100644
--- a/sr_port/stp_gcol_ch.c
+++ b/sr_port/stp_gcol_ch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2002, 2013 Fidelity Information Services, Inc *
+ * Copyright 2002, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,7 +13,11 @@
#include "error.h"
#include "util.h"
-GBLREF boolean_t expansion_failed, retry_if_expansion_fails;
+GBLREF boolean_t expansion_failed, retry_if_expansion_fails;
+#ifdef DEBUG
+GBLREF boolean_t ok_to_UNWIND_in_exit_handling;
+GBLREF int process_exiting;
+#endif
error_def(ERR_MEMORY);
error_def(ERR_VMSMEMORY);
@@ -28,6 +32,14 @@ CONDITION_HANDLER(stp_gcol_ch)
{
UNIX_ONLY(util_out_print("", RESET)); /* Prevent rts_error from flushing error later */
expansion_failed = TRUE;
+# ifdef DEBUG
+ /* We are about to do an UNWIND. If we are already in exit handling code, then we want to avoid an assert
+ * in UNWIND macro so set variable to TRUE. It is okay to do this set because this condition handler will
+ * return to the caller of expand_stp which knows to reset this variable.
+ */
+ if (process_exiting)
+ ok_to_UNWIND_in_exit_handling = TRUE;
+# endif
UNWIND(NULL, NULL);
}
NEXTCH; /* we really need to expand, and there is no memory available, OR, non memory related error */
diff --git a/sr_port/stp_gcol_src.h b/sr_port/stp_gcol_src.h
index b30e47b..3818ff5 100644
--- a/sr_port/stp_gcol_src.h
+++ b/sr_port/stp_gcol_src.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,9 +12,10 @@
#include "mdef.h"
#include <stddef.h>
-
#include "gtm_string.h"
+#include "gtm_stdio.h"
+#include "gtmio.h"
#include "gdsroot.h"
#include "gdskill.h"
#include "gtm_facility.h"
@@ -56,6 +57,12 @@
#include "srcline.h"
#include "opcode.h"
#include "glvn_pool.h"
+#ifdef GTM_CRYPT
+# include "iormdef.h"
+#endif
+#ifdef USHBIN_SUPPORTED
+# include "relinkctl.h"
+#endif
#ifndef STP_MOVE
GBLDEF int indr_stp_low_reclaim_passes = 0;
@@ -98,6 +105,7 @@ GBLREF boolean_t suspend_lvgcol;
GBLREF hash_table_str *complits_hashtab;
GBLREF mval *alias_retarg;
GTMTRIG_ONLY(GBLREF mval dollar_ztwormhole;)
+DEBUG_ONLY(GBLREF boolean_t ok_to_UNWIND_in_exit_handling;)
OS_PAGE_SIZE_DECLARE
@@ -294,6 +302,23 @@ error_def(ERR_STPEXPFAIL);
} \
}
+#define MOVE_WITHIN_STPOOL(cstr, topstr) \
+{ \
+ while (cstr < topstr) \
+ { \
+ /* Determine extent of next contiguous block to move and move it. */ \
+ if (mstr_native_align) \
+ stringpool.free = (unsigned char *)ROUND_UP2((INTPTR_T)stringpool.free, NATIVE_WSIZE); \
+ begaddr = endaddr = (unsigned char *)((*cstr)->addr); \
+ delta = (*cstr)->addr - (char *)stringpool.free; \
+ PROCESS_CONTIGUOUS_BLOCK(begaddr, endaddr, cstr, delta); \
+ blklen = endaddr - begaddr; \
+ if (delta) \
+ memmove(stringpool.free, begaddr, blklen); \
+ stringpool.free += blklen; \
+ } \
+}
+
#define LVZWRITE_BLOCK_GC(LVZWRITE_BLOCK) \
{ \
if ((NULL != (LVZWRITE_BLOCK)) && ((LVZWRITE_BLOCK)->curr_subsc)) \
@@ -350,7 +375,7 @@ static void expand_stp(unsigned int new_size) /* BYPASSOK */
{
if (retry_if_expansion_fails)
ESTABLISH(stp_gcol_ch);
- assert(IS_GTM_IMAGE || IS_MUPIP_IMAGE || IS_GTM_SVC_DAL_IMAGE);
+ assert(IS_GTM_IMAGE || IS_MUPIP_IMAGE);
assert(!stringpool_unexpandable);
DBGSTPGCOL((stderr, "expand_stp(new_size=%u)\n", new_size));
stp_init(new_size);
@@ -470,10 +495,17 @@ void stp_gcol(int space_asked) /* BYPASSOK */
lv_xnew_var *xnewvar;
lvzwrite_datablk *lvzwrblk;
tp_var *restore_ent;
- boolean_t non_mandatory_expansion, exp_gt_spc_needed, first_expansion_try;
+ boolean_t non_mandatory_expansion, exp_gt_spc_needed;
routine_source *rsptr;
glvn_pool_entry *slot, *top;
int i, n;
+ unsigned char *old_free;
+# ifdef USHBIN_SUPPORTED
+ open_relinkctl_sgm *linkctl;
+# endif
+# ifdef GTM_CRYPT
+ d_rm_struct *rm_ptr;
+# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -649,7 +681,25 @@ void stp_gcol(int space_asked) /* BYPASSOK */
for (l = io_root_log_name; 0 != l; l = l->next)
{
if ((IO_ESC != l->dollar_io[0]) && (l->iod->trans_name == l))
+ {
MSTR_STPG_ADD(&l->iod->error_handler);
+# ifdef GTM_CRYPT
+ rm_ptr = (d_rm_struct *)l->iod->dev_sp;
+ if (NULL != rm_ptr)
+ { /* Protect the IVs and KEYs as needed. */
+ if (rm_ptr->input_encrypted)
+ {
+ MSTR_STPG_ADD(&rm_ptr->input_iv);
+ MSTR_STPG_ADD(&rm_ptr->input_key);
+ }
+ if (rm_ptr->output_encrypted)
+ {
+ MSTR_STPG_ADD(&rm_ptr->output_iv);
+ MSTR_STPG_ADD(&rm_ptr->output_key);
+ }
+ }
+# endif
+ }
}
MVAL_STPG_ADD(&dollar_etrap);
MVAL_STPG_ADD(&dollar_system);
@@ -835,9 +885,22 @@ void stp_gcol(int space_asked) /* BYPASSOK */
tf = tf->old_tp_frame;
}
}
+# ifdef USHBIN_SUPPORTED
+ /* Make sure we keep track of the relinkable directory names */
+ for (linkctl = TREF(open_relinkctl_list); NULL != linkctl; linkctl = linkctl->next)
+ {
+ MSTR_STPG_ADD(&linkctl->zro_entry_name);
+ }
+# endif
}
space_before_compact = stringpool.top - stringpool.free; /* Available space before compaction */
DEBUG_ONLY(blklen = stringpool.free - stringpool.base);
+ old_free = stringpool.free;
+ /* Reset stringpool.free in the hope stringpool garbage collection (and expansion if needed) would happen.
+ * If there are any errors in this process, we need to remember to restore stringpool.free as otherwise
+ * any mval in the stringpool could potentially be overwritten later (for a new mval since there is an
+ * incorrect view of available stringpool space) resulting in memory corruption.
+ */
stringpool.free = stringpool.base;
if (topstr != array)
{
@@ -903,29 +966,8 @@ void stp_gcol(int space_asked) /* BYPASSOK */
strpool_base = stringpool.base;
/* Grow stringpool geometrically */
stp_incr = (stringpool.top - stringpool.base) * *incr_factor / STP_NUM_INCRS;
- first_expansion_try = TRUE;
- while (first_expansion_try || (retry_if_expansion_fails && expansion_failed))
+ do
{
- if (!first_expansion_try)
- {
- /* Once we hit the memory wall no more non_mandatory expansions */
- if (non_mandatory_expansion)
- stop_non_mandatory_expansion = TRUE;
- /* We were not able to get the memory we wanted. Plan B it to get as much of what we wanted
- * (down to what was actually needed). If we can't get what was actually needed allow
- * the user to get a memory error.
- */
- if (1 < *incr_factor)
- {
- /* if we hit the memory wall with an elevated incr_factor drop back a notch and retry */
- *incr_factor = *incr_factor - 1;
- stp_incr = (stringpool.top - stringpool.base) * *incr_factor / STP_NUM_INCRS;
- } else
- /* if we are already at the lowest incr_factor half our way down */
- if (stp_incr > space_needed)
- stp_incr = stp_incr / 2;
- }
- first_expansion_try = FALSE;
if (stp_incr < space_needed)
stp_incr = space_needed;
/* If we are asking for more than is actually needed we want to try again if we do not get it. */
@@ -942,7 +984,34 @@ void stp_gcol(int space_asked) /* BYPASSOK */
assert((stp_incr + stringpool.top - stringpool.base) >= (space_needed + blklen));
DBGSTPGCOL((stderr, "incr_factor=%i stp_incr=%i space_needed=%i\n", *incr_factor, stp_incr, space_needed));
expand_stp((unsigned int)(stp_incr + stringpool.top - stringpool.base));
- }
+# ifdef DEBUG
+ /* If expansion failed and stp_gcol_ch did an UNWIND and we were already in exit handling code,
+ * ok_to_UNWIND_in_exit_handling would have been set to avoid an assert in UNWIND macro. Now that
+ * we are back from stp_gcol_ch, reset it so future UNWINDs in exit-handling are assert checked.
+ */
+ if (expansion_failed && process_exiting)
+ ok_to_UNWIND_in_exit_handling = FALSE;
+# endif
+ if (!retry_if_expansion_fails || !expansion_failed)
+ break;
+ /* Once we hit the memory wall no more non_mandatory expansions */
+ if (non_mandatory_expansion)
+ stop_non_mandatory_expansion = TRUE;
+ /* We were not able to get the memory we wanted. Plan B it to get as much of what we wanted
+ * (down to what was actually needed). If we can't get what was actually needed allow
+ * the user to get a memory error.
+ */
+ if (1 < *incr_factor)
+ {
+ /* if we hit the memory wall with an elevated incr_factor drop back a notch and retry */
+ *incr_factor = *incr_factor - 1;
+ stp_incr = (stringpool.top - stringpool.base) * *incr_factor / STP_NUM_INCRS;
+ } else
+ { /* if we are already at the lowest incr_factor half our way down */
+ if (stp_incr > space_needed)
+ stp_incr = stp_incr / 2;
+ }
+ } while (TRUE);
if (strpool_base != stringpool.base) /* expanded successfully */
{
cstr = array;
@@ -958,8 +1027,12 @@ void stp_gcol(int space_asked) /* BYPASSOK */
{ /* Could not expand during forced expansion */
assert(non_mandatory_expansion && stop_non_mandatory_expansion);
if (space_after_compact < space_needed)
+ { /* Restore stringpool.free since no garbage collection happened. */
+ stringpool.free = old_free;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_STPEXPFAIL, 1,
(stp_incr + stringpool.top - stringpool.base));
+ }
+ MOVE_WITHIN_STPOOL(cstr, topstr);
}
*low_reclaim_passes = 0;
} else
@@ -989,19 +1062,7 @@ void stp_gcol(int space_asked) /* BYPASSOK */
*/
cstr = array;
begaddr = endaddr = (unsigned char *)((*cstr)->addr);
- while (cstr < topstr)
- {
- /* Determine extent of next contiguous block to move and move it. */
- if (mstr_native_align)
- stringpool.free = (unsigned char *)ROUND_UP2((INTPTR_T)stringpool.free, NATIVE_WSIZE);
- begaddr = endaddr = (unsigned char *)((*cstr)->addr);
- delta = (*cstr)->addr - (char *)stringpool.free;
- PROCESS_CONTIGUOUS_BLOCK(begaddr, endaddr, cstr, delta);
- blklen = endaddr - begaddr;
- if (delta)
- memmove(stringpool.free, begaddr, blklen);
- stringpool.free += blklen;
- }
+ MOVE_WITHIN_STPOOL(cstr, topstr);
}
# ifdef STP_MOVE
if (0 != stp_move_count)
diff --git a/sr_port/str2gvargs.c b/sr_port/str2gvargs.c
index 0203756..e5a1133 100644
--- a/sr_port/str2gvargs.c
+++ b/sr_port/str2gvargs.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2002, 2010 Fidelity Information Services, Inc *
+ * Copyright 2002, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -29,6 +29,17 @@
#include "gv_trigger.h"
#endif
+error_def(ERR_NOTGBL);
+error_def(ERR_GVINVALID);
+error_def(ERR_LPARENREQD);
+error_def(ERR_NUMUNXEOR);
+error_def(ERR_STRUNXEOR);
+error_def(ERR_DLRCUNXEOR);
+error_def(ERR_DLRCTOOBIG);
+error_def(ERR_EORNOTFND);
+error_def(ERR_RPARENREQD);
+error_def(ERR_DLRCILLEGAL);
+
static mval subsc[MAX_GVSUBSCRIPTS]; /* At return, op_gvargs elements will be pointing to elements of this array, hence static */
static MSTR_DEF(subsc_buffer, 0, NULL); /* Buffer space (subsc_buffer.addr) will be allocated on the first call.
* Buffer space to hold string mvals in subsc; we don't want to use stringpool because
@@ -41,22 +52,11 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
{ /* IMPORTANT : op_gvargs will point to static area which gets overwritten by the next call to this function. Callers should
make a copy of op_gvargs if necessary */
- char *p1, *p2, *c_top, *c_ref, ch, *subsc_ptr, *dstptr, *strnext;
- int count;
- mval *spt;
- int chcode, chtmp;
+ boolean_t concat, dot_seen, dollarzch, isdolar, naked;
+ char *c_ref, *c_top, ch, *dstptr, *p1, *p2, *strnext, *subsc_ptr;
+ int chcode, chtmp, count;
mstr_len_t chlen;
- boolean_t naked, concat, dot_seen, dollarzch, isdolar;
- error_def(ERR_NOTGBL);
- error_def(ERR_GVINVALID);
- error_def(ERR_LPARENREQD);
- error_def(ERR_NUMUNXEOR);
- error_def(ERR_STRUNXEOR);
- error_def(ERR_DLRCUNXEOR);
- error_def(ERR_DLRCTOOBIG);
- error_def(ERR_EORNOTFND);
- error_def(ERR_RPARENREQD);
- error_def(ERR_DLRCILLEGAL);
+ mval *spt;
assert(SIZEOF(op_gvargs->count) == SIZEOF(op_gvargs->args[0]));
naked = FALSE;
@@ -74,7 +74,7 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
spt = subsc;
count = 0;
if (0 >= len || '^' != *cp++)
- rts_error(VARLSTCNT(4) ERR_NOTGBL, 2, (len > 0) ? len : 0, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOTGBL, 2, (len > 0) ? len : 0, c_ref);
spt->mvtype = MV_STR;
spt->str.addr = cp;
ch = *cp;
@@ -86,12 +86,12 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
{
cp++;
if (!(VALFIRSTCHAR_WITH_TRIG(ch)))
- rts_error(VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref);
for ( ; cp < c_top && *cp != '('; )
{
ch = *cp++;
if (!ISALPHA_ASCII(ch) && !ISDIGIT_ASCII(ch))
- rts_error(VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref);
}
spt->str.len = INTCAST(cp - spt->str.addr);
op_gvargs->args[count] = spt;
@@ -102,7 +102,7 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
if (cp < c_top)
{
if ('(' != *cp++)
- rts_error(VARLSTCNT(4) ERR_LPARENREQD, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_LPARENREQD, 2, len, c_ref);
for (; ;)
{
spt->mvtype = MV_STR;
@@ -119,7 +119,7 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
for (; ;)
{
if (cp == c_top)
- rts_error(VARLSTCNT(4) ERR_STRUNXEOR, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_STRUNXEOR, 2, len, c_ref);
if ('\"' == *cp)
if ('\"' != *++cp)
break;
@@ -143,12 +143,12 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
} else if ('$' == ch)
{
cp++;
- chtmp = toupper(*cp);
+ chtmp = TOUPPER(*cp);
isdolar = (3 <= c_top - cp && 'C' == chtmp || '(' == cp[1]);
if (!isdolar)
isdolar = (5 <= c_top - cp && 'Z' == chtmp && 'C' == cp[1] && 'H' == cp[2] && '(' == cp[3]);
if (!isdolar)
- rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
if ('Z' == chtmp)
{
@@ -163,7 +163,7 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
{
A2I(cp, c_top, chcode);
if (0 > chcode)
- rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
dstptr = (!concat) ? subsc_ptr : p1;
@@ -172,23 +172,24 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
if (255 < chcode)
{
if (dollarzch)
- rts_error(VARLSTCNT(6) ERR_DLRCTOOBIG, 4, len, c_ref,
- LEN_AND_LIT("$CHAR()"));
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_DLRCTOOBIG, 4,
+ len, c_ref, LEN_AND_LIT("$CHAR()"));
else
- rts_error(VARLSTCNT(6) ERR_DLRCTOOBIG, 4, len, c_ref,
- LEN_AND_LIT("$ZCHAR()"));
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_DLRCTOOBIG, 4,
+ len, c_ref, LEN_AND_LIT("$ZCHAR()"));
}
*dstptr = chcode;
chlen = 1;
}
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
else {
strnext = (char *)UTF8_WCTOMB(chcode, dstptr);
chlen = INTCAST(strnext - dstptr);
if (0 == chlen)
- rts_error(VARLSTCNT(5) ERR_DLRCILLEGAL, 3, len, c_ref, chcode);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_DLRCILLEGAL, 3,
+ len, c_ref, chcode);
}
-#endif
+# endif
if (!concat)
{
spt->str.addr = subsc_ptr;
@@ -205,11 +206,11 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
{
concat = TRUE;
if (++cp == c_top)
- rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
continue;
}
if (')' != *cp)
- rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
break;
}
cp++;
@@ -223,7 +224,7 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
{
dot_seen = FALSE;
if (!ISDIGIT_ASCII(ch) && '.' != ch && '-' != ch && '+' != ch)
- rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
if (!concat)
{
spt->str.addr = subsc_ptr;
@@ -234,7 +235,7 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
for (; ;)
{
if (cp == c_top)
- rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
if (!ISDIGIT_ASCII(*cp))
{
if ('.' != *cp)
@@ -242,7 +243,7 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
else if (!dot_seen)
dot_seen = TRUE;
else
- rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
}
*p1++ = *cp++;
}
@@ -271,9 +272,9 @@ boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
cp++;
}
if (')' != *cp++)
- rts_error(VARLSTCNT(4) ERR_RPARENREQD, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_RPARENREQD, 2, len, c_ref);
if (cp < c_top)
- rts_error(VARLSTCNT(4) ERR_EORNOTFND, 2, len, c_ref);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_EORNOTFND, 2, len, c_ref);
}
op_gvargs->count = count;
return naked;
diff --git a/sr_port/stringpool.h b/sr_port/stringpool.h
index bf2361d..accf6e2 100644
--- a/sr_port/stringpool.h
+++ b/sr_port/stringpool.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -65,3 +65,28 @@ GBLREF boolean_t stringpool_unexpandable;
INVOKE_STP_GCOL(lcl_spc_needed); \
assert(IS_STP_SPACE_AVAILABLE(lcl_spc_needed)); \
}
+
+#define ADD_TO_STPARRAY(PTR, PTRARRAY, PTRARRAYCUR, PTRARRAYTOP, TYPE) \
+{ \
+ GBLREF mstr **stp_array; \
+ GBLREF int stp_array_size; \
+ \
+ if (NULL == PTRARRAY) \
+ { \
+ if (NULL == stp_array) \
+ { \
+ /* Same initialization as is in stp_gcol_src.h */ \
+ stp_array = (mstr **)malloc((stp_array_size = STP_MAXITEMS) * SIZEOF(mstr *)); \
+ } \
+ PTRARRAYCUR = PTRARRAY = (TYPE **)stp_array; \
+ PTRARRAYTOP = PTRARRAYCUR + stp_array_size; \
+ } else if (PTRARRAYCUR >= PTRARRAYTOP) \
+ { \
+ stp_expand_array(); \
+ PTRARRAYCUR = (TYPE **)stp_array + (PTRARRAYCUR - PTRARRAY); \
+ PTRARRAY = (TYPE **)stp_array; \
+ PTRARRAYTOP = PTRARRAY + stp_array_size; \
+ } \
+ *PTRARRAYCUR++ = PTR; \
+}
+
diff --git a/sr_port/symbinit.c b/sr_port/symbinit.c
index adc2780..f77f7f9 100644
--- a/sr_port/symbinit.c
+++ b/sr_port/symbinit.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,16 +12,24 @@
#include "mdef.h"
#include "gtm_string.h"
+#include "gtm_stdio.h"
+#include "lv_val.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "mv_stent.h" /* this includes lv_val.h which also includes hashtab_mname.h and hashtab.h */
#include "stack_frame.h"
#include "mdq.h"
+#include "gdsroot.h"
+#include "gtm_facility.h"
+#include "fileinfo.h"
+#include "gdsbt.h"
+#include "gdsfhead.h"
+#include "alias.h"
#define MVST_STAB_SIZE (SIZEOF(*mv_chain) - SIZEOF(mv_chain->mv_st_cont) + SIZEOF(mv_chain->mv_st_cont.mvs_stab))
GBLREF symval *curr_symval;
-
GBLREF mv_stent *mv_chain;
GBLREF unsigned char *stackbase, *stacktop, *msp, *stackwarn;
GBLREF stack_frame *frame_pointer;
@@ -31,13 +39,12 @@ error_def(ERR_STACKCRIT);
int4 symbinit(void)
{
- unsigned char *msp_save;
+ int size;
+ int4 shift_size, ls_size, temp_size;
mv_stent *mv_st_ent, *mvst_tmp, *mvst_prev;
- stack_frame *fp,*fp_prev,*fp_fix;
+ stack_frame *fp, *fp_prev, *fp_fix;
symval *ptr;
- int4 shift_size, ls_size, temp_size;
- int size;
- unsigned char *old_sp, *top, *l_syms;
+ unsigned char *l_syms, *msp_save, *old_sp, *top;
if (frame_pointer->type & SFT_COUNT)
{
@@ -53,9 +60,9 @@ int4 symbinit(void)
if (msp <= stacktop)
{
msp = msp_save;
- rts_error(VARLSTCNT(1) ERR_STACKOFLOW);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKOFLOW);
} else
- rts_error(VARLSTCNT(1) ERR_STACKCRIT);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKCRIT);
}
frame_pointer->l_symtab = (ht_ent_mname **)msp;
}
@@ -88,9 +95,9 @@ int4 symbinit(void)
if (msp <= stacktop)
{
msp = old_sp;
- rts_error(VARLSTCNT(1) ERR_STACKOFLOW);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKOFLOW);
} else
- rts_error(VARLSTCNT(1) ERR_STACKCRIT);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKCRIT);
}
memmove(msp, old_sp, top - (unsigned char *)old_sp); /* Shift stack w/possible overlapping range */
if (shift_size > MVST_STAB_SIZE)
@@ -137,7 +144,6 @@ int4 symbinit(void)
}
}
mv_st_ent->mv_st_cont.mvs_stab = (symval *)NULL; /* special case this so failed initialization can be detected */
-
memset(l_syms, 0, ls_size);
size++;
ptr = (symval *)malloc(SIZEOF(symval));
@@ -163,6 +169,8 @@ int4 symbinit(void)
ptr->symvlvl = 1;
GTMTRIG_ONLY(ptr->trigr_symval = FALSE);
ptr->alias_activity = FALSE;
+ DBGRFCT((stderr,"symbinit: Allocated new symbol table at 0x"lvaddr" pushing old symbol table on M stack (0x"lvaddr")\n",
+ ptr, curr_symval));
curr_symval = ptr;
mv_st_ent->mv_st_cont.mvs_stab = ptr;
return shift_size;
diff --git a/sr_port/t_end.c b/sr_port/t_end.c
index 874e349..45d5a2d 100644
--- a/sr_port/t_end.c
+++ b/sr_port/t_end.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -1479,7 +1479,7 @@ trans_num t_end(srch_hist *hist1, srch_hist *hist2, trans_num ctn)
* effectively gets deferred but does happen.
*/
lcl_ss_ctx = SS_CTX_CAST(cs_addrs->ss_ctx);
- if (lcl_ss_ctx && FASTINTEG_IN_PROG(lcl_ss_ctx))
+ if (lcl_ss_ctx && FASTINTEG_IN_PROG(lcl_ss_ctx) && (blkid < lcl_ss_ctx->total_blks))
WRITE_SNAPSHOT_BLOCK(cs_addrs, cr, NULL, blkid, lcl_ss_ctx);
}
# endif
diff --git a/sr_port/t_qread.c b/sr_port/t_qread.c
index 1678027..734b5c2 100644
--- a/sr_port/t_qread.c
+++ b/sr_port/t_qread.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -299,7 +299,7 @@ sm_uc_ptr_t t_qread(block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr_out
return (sm_uc_ptr_t)(mm_read(blk));
}
# ifdef GTM_CRYPT
- if ((GTMCRYPT_INVALID_KEY_HANDLE == csa->encr_key_handle) && !IS_BITMAP_BLK(blk))
+ if (csd->is_encrypted && (GTMCRYPT_INVALID_KEY_HANDLE == csa->encr_key_handle) && !IS_BITMAP_BLK(blk))
{ /* A non-GT.M process is attempting to read a non-bitmap block but doesn't have a valid encryption key handle. This
* is an indication that the process encountered an error during db_init and reported it with a -W- severity. But,
* since the block it is attempting to read can be in the unencrypted shared memory, we cannot let it access it
@@ -518,7 +518,7 @@ sm_uc_ptr_t t_qread(block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr_out
* do a read memory barrier to ensure we read a consistent state. Otherwise, we could see
* cr->in_tend as 0 even though it is actually non-zero in another processor (due to cache
* coherency delays in multi-processor environments) and this could lead to mysterious
- * failures including GTMASSERTs and database damage as the validation logic in t_end/tp_tend
+ * failures including assertpros and database damage as the validation logic in t_end/tp_tend
* relies on the fact that the cr->in_tend check here is accurate as of this point.
*
* Note that on architectures where a change done by another process needs two steps to be made
@@ -686,15 +686,10 @@ sm_uc_ptr_t t_qread(block_id blk, sm_int_ptr_t cycle, cache_rec_ptr_ptr_t cr_out
break;
ocnt++;
assert((0 == was_crit) || (1 == was_crit));
- /* if we held crit while entering t_qread we might need BAD_LUCK_ABOUNDS - 1 passes.
- * otherwise we might need BAD_LUCK_ABOUNDS passes. if we are beyond this GTMASSERT.
+ /* If we held crit while entering t_qread we might need BAD_LUCK_ABOUNDS - 1 passes.
+ * Otherwise, we might need BAD_LUCK_ABOUNDS passes if we are beyond this assertpro.
*/
- if ((BAD_LUCK_ABOUNDS - was_crit) < ocnt)
- {
- assert(!hold_onto_crit);
- assert(!csa->now_crit);
- GTMASSERT;
- }
+ assertpro((BAD_LUCK_ABOUNDS - was_crit) >= ocnt);
if (!csa->now_crit && !hold_onto_crit)
grab_crit(gv_cur_region);
} while (TRUE);
diff --git a/sr_port/t_write.c b/sr_port/t_write.c
index e6a6a0d..a2980fd 100644
--- a/sr_port/t_write.c
+++ b/sr_port/t_write.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2013 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -77,10 +77,11 @@ cw_set_element *t_write (
sgmnt_addrs *csa;
blk_hdr_ptr_t old_block;
unsigned int bsiz;
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
csa = cs_addrs;
horiz_growth = FALSE;
-
/* When the following two asserts trip, we should change the data types of prev_first_off
* and prev_next_off, so they satisfy the assert.
*/
@@ -127,7 +128,15 @@ cw_set_element *t_write (
} else
{
new_cse = FALSE;
- assert(cse->done);
+# ifdef DEBUG
+ if (!cse->done)
+ { /* This is a restartable situation. Since this routine does not return
+ * a failure code, we continue and expect tp_tend to detect this.
+ */
+ assert(CDB_STAGNATE > t_tries);
+ TREF(donot_commit) |= DONOTCOMMIT_T_WRITE_CSE_DONE;
+ }
+# endif
assert(dollar_tlevel >= cse->t_level);
if (cse->t_level != dollar_tlevel)
{
@@ -163,14 +172,16 @@ cw_set_element *t_write (
{
case kill_t_create:
assert(CDB_STAGNATE > t_tries);
+ DEBUG_ONLY(TREF(donot_commit) |= DONOTCOMMIT_T_WRITE_CSE_MODE;)
cse->mode = gds_t_create;
break;
case kill_t_write:
assert(CDB_STAGNATE > t_tries);
+ DEBUG_ONLY(TREF(donot_commit) |= DONOTCOMMIT_T_WRITE_CSE_MODE;)
cse->mode = gds_t_write;
break;
default:
- ;
+ break;
}
}
tp_cse = cse;
diff --git a/sr_port/term_setup.h b/sr_port/term_setup.h
index d4549b3..d885c58 100644
--- a/sr_port/term_setup.h
+++ b/sr_port/term_setup.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,6 @@
#ifndef TERM_SETUP_INCLUDED
#define TERM_SETUP_INCLUDED
-void term_setup(bool ctrlc_enable);
+void term_setup(boolean_t ctrlc_enable);
#endif /* TERM_SETUP_INCLUDED */
diff --git a/sr_port/tp.h b/sr_port/tp.h
index 5aca7a5..1875bf8 100644
--- a/sr_port/tp.h
+++ b/sr_port/tp.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -367,7 +367,7 @@ typedef struct ua_list_struct
*/
typedef struct gv_orig_key_struct
{
- int4 gv_orig_key[DIVIDE_ROUND_UP((SIZEOF(gv_key) + MAX_KEY_SZ + 1), SIZEOF(int4))];
+ gv_key gv_orig_key[DBKEYALLOC(MAX_KEY_SZ)];
}gv_orig_key_array;
GBLREF block_id t_fail_hist_blk[];
diff --git a/sr_port/tp_frame.h b/sr_port/tp_frame.h
index 4425643..b075753 100644
--- a/sr_port/tp_frame.h
+++ b/sr_port/tp_frame.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -45,8 +45,8 @@
* of "lv" through a "KILL *". Necessary because we need the "lv_val" of "lv" \
* untouched (i.e. not freed and/or reused after a "kill *"). \
*/ \
- INCR_CREFCNT(lv); \
INCR_TREFCNT(lv); \
+ INCR_CREFCNT(lv); \
assert(1 < (lv)->stats.trefcnt); \
assert(0 < (lv)->stats.crefcnt); \
(tf)->vars = restore_ent; \
@@ -91,4 +91,5 @@ typedef struct tp_frame_struct
mstr extnam_str; /* saved/restored only for OUTERMOST tstart */
struct tp_frame_struct *old_tp_frame;
unsigned char *restart_ctxt;
+ struct lv_val_struct *active_lv; /* saved/restored only for OUTERMOST tstart */
} tp_frame;
diff --git a/sr_port/tp_restart.c b/sr_port/tp_restart.c
index ff2f179..99992fc 100644
--- a/sr_port/tp_restart.c
+++ b/sr_port/tp_restart.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -124,7 +124,7 @@ error_def(ERR_TPRETRY);
error_def(ERR_TRESTLOC);
error_def(ERR_TRESTNOT);
-#define GVNAME_UNKNOWN "*UNKNOWN"
+#define GVNAME_UNKNOWN "*BITMAP"
static readonly char gvname_unknown[] = GVNAME_UNKNOWN;
static readonly int4 gvname_unknown_len = STR_LIT_LEN(GVNAME_UNKNOWN);
@@ -148,6 +148,15 @@ CONDITION_HANDLER(tp_restart_ch)
# endif
GTMTRIG_ONLY(DBGTRIGR((stderr, "tp_restart_ch: ERROR!! unwinding C frame to return. Error is %d, tprestart_state is %d\n",
arg, tprestart_state)));
+ /* It is possible that dollar_tlevel at the time of the ESTABLISH_RET was higher than the current dollar_tlevel.
+ * This is because tp_unwind could have decreased dollar_tlevel. Even though dollar_tlevel before the UNWIND done
+ * below is not the same as that at ESTABLISH_RET time, the flow of control happens correctly so tp_restart eventually
+ * bubbles back to the op_tstart at $tlevel=1 and resumes execution. So treat this as an exception and adjust
+ * active_ch->dollar_tlevel so it is in sync with the current dollar_tlevel. This prevents an assert failure in UNWIND.
+ * START_CH would have done a active_ch-- so we need a active_ch[1] to get at the desired active_ch.
+ */
+ UNIX_ONLY(assert(active_ch[1].dollar_tlevel >= dollar_tlevel);)
+ UNIX_ONLY(DEBUG_ONLY(active_ch[1].dollar_tlevel = dollar_tlevel;))
UNWIND(NULL, NULL);
}
@@ -670,7 +679,7 @@ int tp_restart(int newlevel, boolean_t handle_errors_internally)
assert((void *)mvc < (void *)frame_pointer);
assert(mvc == tf->mvc);
assert(mvc->mv_st_cont.mvs_tp_holder.tphold_tlevel == (dollar_tlevel - 1));
- DBGEHND((stderr, "tp_restart: Resetting msp from 0x"lvaddr", to 0x"lvaddr" (diff=%d)\n",
+ DBGEHND((stderr, "tp_restart: Resetting msp from 0x"lvaddr" to 0x"lvaddr" (diff=%d)\n",
msp, mvc, INTCAST((unsigned char *)mvc - msp)));
mv_chain = mvc;
msp = (unsigned char *)mvc;
diff --git a/sr_port/tp_tend.c b/sr_port/tp_tend.c
index e49d443..67c9958 100644
--- a/sr_port/tp_tend.c
+++ b/sr_port/tp_tend.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -1508,14 +1508,15 @@ boolean_t tp_tend()
assert(0 != jnl_fence_ctl.token);
jfb = si->jnl_head;
assert(NULL != jfb);
- /* Fill in "num_participants" field in TSET/TKILL/TZKILL/TZTRIG/TZTWORM record.
- * The rest of the records (USET/UKILL/UZKILL/UZTRIG/UZTWORM) dont have this initialized.
+ /* Fill in "num_participants" field in TSET/TKILL/TZKILL/TZTRIG/TZTWORM/TLGTRIG record.
+ * The rest of the records (USET/UKILL/UZKILL/UZTRIG/UZTWORM/ULGTRIG) dont have this initialized.
* Recovery looks at this field only in the T* records.
*/
rec = (jnl_record *)jfb->buff;
assert(IS_TUPD(jfb->rectype));
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(jfb->rectype));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(jfb->rectype));
assert(&rec->jrec_set_kill.num_participants == &rec->jrec_ztworm.num_participants);
+ assert(&rec->jrec_set_kill.num_participants == &rec->jrec_lgtrig.num_participants);
rec->jrec_set_kill.num_participants = replay_jnl_participants;
DEBUG_ONLY(++tmp_jnl_participants;)
do
diff --git a/sr_port/tp_unwind.c b/sr_port/tp_unwind.c
index 8e426ff..a436a5c 100644
--- a/sr_port/tp_unwind.c
+++ b/sr_port/tp_unwind.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -64,6 +64,7 @@ GBLREF uint4 dollar_tlevel;
GBLREF symval *curr_symval;
GBLREF uint4 process_id;
GBLREF sgmnt_addrs *csa;
+GBLREF lv_val *active_lv;
#ifdef GTM_TRIGGER
GBLREF int tprestart_state; /* When triggers restart, multiple states possible. See tp_restart.h */
#endif
@@ -104,7 +105,6 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
tp_var *restore_ent;
mv_stent *mvc;
boolean_t restore_lv, rollback_locks;
- lvscan_blk *lvscan, *lvscan_next, first_lvscan;
int elemindx, rc;
lvTree *lvt_child;
@@ -112,12 +112,33 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
DEFER_INTERRUPTS(INTRPT_IN_TP_UNWIND);
/* Unwind the requested TP levels */
# if defined(DEBUG_REFCNT) || defined(DEBUG_ERRHND)
- DBGFPF((stderr, "\ntp_unwind: Beginning TP unwind process\n"));
+ DBGFPF((stderr, "\ntp_unwind: Beginning TP unwind process - reason: %d\n", invocation_type));
# endif
+ assert((COMMIT_INVOCATION == invocation_type) || (RESTART_INVOCATION == invocation_type)
+ || (ROLLBACK_INVOCATION == invocation_type));
+ /* If restarting or rolling back, clear active_lv (if it is non-NULL now) since it was NULL at TSTART time. */
+ if (RESTART_INVOCATION == invocation_type)
+ {
+ UNDO_ACTIVE_LV(actlv_tp_unwind_restart);
+ } else if (ROLLBACK_INVOCATION == invocation_type)
+ {
+ UNDO_ACTIVE_LV(actlv_tp_unwind_rollback);
+ } else
+ {
+ ASSERT_ACTIVELV_GOOD(active_lv);
+ if (0 == newlevel)
+ { /* outermost TCOMMIT. Restore active_lv to what it was at implicit TSTART time if it was non-NULL */
+ assert(NULL != tp_pointer);
+ assert(NULL == tp_pointer->old_tp_frame);
+ if (tp_pointer->implicit_tstart)
+ {
+ lv = tp_pointer->active_lv;
+ if (NULL != lv)
+ SET_ACTIVE_LV(lv, FALSE, actlv_tp_unwind_commit);
+ }
+ }
+ }
restore_lv = (RESTART_INVOCATION == invocation_type);
- lvscan = &first_lvscan;
- lvscan->next = NULL;
- lvscan->elemcnt = 0;
assert((tp_sp <= tpstackbase) && (tp_sp > tpstacktop));
assert((tp_pointer <= (tp_frame *)tpstackbase) && (tp_pointer > (tp_frame *)tpstacktop));
for (tl = dollar_tlevel; tl > newlevel; --tl)
@@ -140,12 +161,15 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
assert(0 < curr_lv->stats.trefcnt);
assert(curr_lv->tp_var);
assert(curr_lv->tp_var == restore_ent);
+ DBGRFCT((stderr, "\ntp_unwind: Top of restore-ent loop - curr_lv: 0x"lvaddr" save_lv: 0x"lvaddr
+ " restore_ent: 0x"lvaddr"\n", curr_lv, save_lv, restore_ent));
/* In order to restart sub-transactions, this would have to maintain
* the chain that currently is not built by op_tstart()
*/
if (restore_lv)
{
- rc = tp_unwind_restlv(curr_lv, save_lv, restore_ent, NULL, tprestart_rc);
+ DBGRFCT((stderr, "\ntp_unwind: Need to restore curr_lv which has been copied\n"));
+ rc = tp_unwind_restlv(curr_lv, save_lv, restore_ent, TRUE, tprestart_rc);
# ifdef GTM_TRIGGER
if (0 != rc)
{
@@ -172,19 +196,9 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
lv_kill(save_lv, DOTPSAVE_FALSE, DO_SUBTREE_TRUE);
}
restore_ent->var_cloned = FALSE;
- } else
- { /* If not cloned, we still have to reduce the reference counts of any
- * container vars in the untouched tree that were added to keep anything
- * they referenced from disappearing.
- */
- DBGRFCT((stderr, "\ntp_unwind: Not restoring curr_lv and is NOT cloned\n"));
- lvt_child = LV_GET_CHILD(curr_lv);
- if (NULL != lvt_child)
- {
- DBGRFCT((stderr, "\ntp_unwind: curr_lv has children and so reducing ref counts\n"));
- TPUNWND_CNTNRS_IN_TREE(curr_lv);
- }
- }
+ } /* Else, if was not cloned, there's nothing more to do for this entry except common refcnt maint below
+ * since any var we visited at TSTART has its own restore_ent to process it on the way out.
+ */
LV_FREESLOT(save_lv);
/* Not easy to predict what the trefcnt will be except that it should be greater than zero. In
* most cases, it will have its own hash table ref plus the extras we added but it is also
@@ -194,9 +208,10 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
*/
assert(0 < curr_lv->stats.trefcnt);
assert(0 < curr_lv->stats.crefcnt);
- DECR_CREFCNT(curr_lv); /* Remove the copy refcnt we added in in op_tstart() or lv_newname() */
+ DECR_CREFCNT(curr_lv); /* Remove refcnt bumps added in in op_tstart() or lv_newname() */
DECR_BASE_REF_NOSYM(curr_lv, FALSE);
curr_lv->tp_var = NULL;
+ curr_lv->stats.tstartcycle = 0; /* As if had done nothing with var in this sub-transaction */
tp_pointer->vars = restore_ent->next;
free(restore_ent);
}
@@ -219,7 +234,8 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
if ((0 != newlevel) && restore_lv)
{ /* Restore current context (without releasing) */
assertpro(NULL != tp_pointer);
- DBGRFCT((stderr, "\n\n** tp_unwind: Newlevel (%d) != 0 loop processing\n", newlevel));
+ DBGRFCT((stderr, "\n\n** tp_unwind: Restore target unwind TP level (level %d) local vars - tp_pointer = 0x"lvaddr
+ "\n", newlevel, tp_pointer));
for (restore_ent = tp_pointer->vars; NULL != restore_ent; restore_ent = restore_ent->next)
{
curr_lv = restore_ent->current_value;
@@ -231,7 +247,7 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
assert(curr_lv->tp_var);
assert(curr_lv->tp_var == restore_ent);
assert(0 < curr_lv->stats.trefcnt);
- rc = tp_unwind_restlv(curr_lv, save_lv, restore_ent, &lvscan, tprestart_rc);
+ rc = tp_unwind_restlv(curr_lv, save_lv, restore_ent, FALSE, tprestart_rc);
# ifdef GTM_TRIGGER
if (0 != rc)
{
@@ -245,41 +261,7 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
assert(0 < curr_lv->stats.trefcnt); /* Should have its own hash table ref plus the extras we added */
assert(0 < curr_lv->stats.crefcnt);
}
- /* If we have any lv_vals queued up to be scanned for container vars, do that now */
- DBGRFCT((stderr, "\ntp_unwind: Starting deferred rescan of lv trees needing refcnt processing\n"));
- while (0 < lvscan->elemcnt)
- {
- assert(ARY_SCNCNTNR_DIM >= lvscan->elemcnt);
- for (elemindx = 0; lvscan->elemcnt > elemindx; ++elemindx)
- {
- lv = lvscan->ary_scncntnr[elemindx];
- DBGRFCT((stderr, "\n**tp_unwind_process_lvscan_array: Deferred processing lv 0x"lvaddr"\n", lv));
- assert(LV_IS_BASE_VAR(lv));
- /* This is the final level being restored so redo the counters on these vars */
- TPREST_CNTNRS_IN_TREE(lv);
- }
- /* If we allocated any secondary blocks, we are done with them now so release them. Only the
- * very last block on the chain is the original block that was automatically allocated which
- * should not be freed in this fashion.
- */
- lvscan_next = lvscan->next;
- if (NULL != lvscan_next)
- { /* There is another block on the chain so this one can be freed */
- free(lvscan);
- DBGRFCT((stderr, "\ntp_unwind_process_lvscan_array: Freeing lvscan array\n"));
- lvscan = lvscan_next;
- } else
- { /* Since this is the original block allocated on the C stack which we may reuse,
- * zero the element count.
- */
- lvscan->elemcnt = 0;
- DBGRFCT((stderr, "\ntp_unwind_process_lvscan_array: Setting elemcnt to 0 in original "
- "lvscan block\n"));
- assert(lvscan == &first_lvscan);
- }
- }
}
- assert(0 == lvscan->elemcnt); /* verify no elements queued that were not scanned */
rollback_locks = (COMMIT_INVOCATION != invocation_type);
for (prior = &mlk_pvt_root, mlkp = *prior; NULL != mlkp; mlkp = *prior)
{
@@ -322,30 +304,29 @@ void tp_unwind(uint4 newlevel, enum tp_unwind_invocation invocation_type, int *t
}
-/* Restore given local variable from supplied TP restore entry into given symval. Note lvscan_anchor will only be non-NULL
- * for the final level we are restoring (but not unwinding). We don't need to restore counters for any vars except the
- * very last level.
+/* Restore given local variable from supplied TP restore entry into given symval. Note clearTStartCycle is FALSE
+ * for the final level we are restoring (but not unwinding).
*
* The return code is only used when unrolling the M stack runs into a trigger base frame which must be unrolled
* by gtm_trigger. A non-zero return code signals to tp_unwind() that it needs to rethrow the tprestart error.
*/
-int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, lvscan_blk **lvscan_anchor, int *tprestart_rc)
+int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, boolean_t clearTStartCycle, int *tprestart_rc)
{
ht_ent_mname *tabent;
lv_val *inuse_lv;
int elemindx;
mv_stent *mvc;
- lvscan_blk *lvscan, *newlvscan;
lvTree *lvt_child;
boolean_t var_cloned;
assert(curr_lv);
assert(LV_IS_BASE_VAR(curr_lv));
assert(curr_lv->tp_var);
- DBGRFCT((stderr, "\ntp_unwind_restlv: Entered for varname: '%.*s' curr_lv: 0x"lvaddr" save_lv: 0x"lvaddr"\n",
- restore_ent->key.var_name.len, restore_ent->key.var_name.addr, curr_lv, save_lv));
- DBGRFCT((stderr, "tp_unwind_restlv: tp_pointer/current: fp: 0x"lvaddr"/0x"lvaddr" mvc: 0x"lvaddr"/0x"lvaddr
- " symval: 0x"lvaddr"/0x"lvaddr"\n",
+ DBGRFCT((stderr, "\ntp_unwind_restlv: Entered for varname: '%.*s' curr_lv: 0x"lvaddr" save_lv: 0x"lvaddr
+ " restore_ent: 0x"lvaddr"\n", restore_ent->key.var_name.len, restore_ent->key.var_name.addr, curr_lv, save_lv,
+ restore_ent));
+ DBGRFCT((stderr, "tp_unwind_restlv: tp_pointer->fp/frame_pointer: 0x"lvaddr"/0x"lvaddr" tp_pointer->mvc/mv_chain: 0x"
+ lvaddr"/0x"lvaddr" tp_pointer->symval/curr_symval: 0x"lvaddr"/0x"lvaddr"\n",
tp_pointer->fp, frame_pointer, tp_pointer->mvc, mv_chain, tp_pointer->sym, curr_symval));
/* First get the stack in the position where we can actually process this entry. Need to make sure we are processing
@@ -402,8 +383,8 @@ int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, lvsc
{
if (inuse_lv)
DECR_BASE_REF_RQ(tabent, inuse_lv, FALSE);
- DBGRFCT((stderr, "tp_unwind: hte 0x"lvaddr" being reset from 0x"lvaddr" to 0x"lvaddr"\n",
- tabent, tabent->value, curr_lv));
+ DBGRFCT((stderr, "tp_unwind_restlv: hte 0x"lvaddr" being reset from 0x"lvaddr" to 0x"lvaddr
+ " in %s at line %d\n", tabent, tabent->value, curr_lv, __FILE__, __LINE__));
tabent->value = (void *)curr_lv;
INCR_TREFCNT(curr_lv); /* Back in the hash table, bump its reference */
}
@@ -413,7 +394,7 @@ int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, lvsc
*/
if (lvt_child = LV_GET_CHILD(curr_lv)) /* Note assignment */
{
- DBGRFCT((stderr, "\ntp_unwind_restlv: Killing children of curr_lv 0x"lvaddr"\n", curr_lv));
+ DBGRFCT((stderr, "\ntp_unwind_restlv: Killing child tree of curr_lv 0x"lvaddr"\n", curr_lv));
assert((lvTreeNode *)curr_lv == LVT_PARENT(lvt_child));
LV_CHILD(curr_lv) = NULL; /* prevent recursion due to alias containers */
lv_killarray(lvt_child, FALSE);
@@ -441,7 +422,7 @@ int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, lvsc
assert(0 < curr_lv->stats.crefcnt);
assert(8 == (OFFSETOF(lv_val, tp_var) - OFFSETOF(lv_val, has_aliascont)));
curr_lv->has_aliascont = save_lv->has_aliascont;
- DBGALS_ONLY(curr_lv->lvmon_mark = save_lv->has_aliascont);
+ DBGALS_ONLY(curr_lv->lvmon_mark = save_lv->lvmon_mark);
assert(save_lv->tp_var == curr_lv->tp_var); /* no need to copy this field */
/* save_lv -> curr_lv Copy done */
/* Some fixup may need to be done if the variable was cloned (and thus moved around) */
@@ -451,29 +432,6 @@ int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, lvsc
assert(LVT_PARENT(lvt_child) == ((lvTreeNode *)curr_lv->tp_var->save_value));
LV_CHILD(save_lv) = NULL; /* now that curr_lv->tp_var->var_cloned has been reset */
LVT_PARENT(lvt_child) = (lvTreeNode *)curr_lv;
- if (curr_lv->has_aliascont && (NULL != lvscan_anchor))
- { /* Some ref counts need to be restored for arrays this tree points to -- but only if the
- * array contains pointers (alias containers).
- */
- DBGRFCT((stderr, "\ntp_unwind_restlv: Putting lv 0x:"lvaddr" on the lvscan list\n", curr_lv));
- /* This array needs to have container pointer target reference counts reestablished. Record
- * the lv so this can happen after all vars are restored.
- */
- lvscan = *lvscan_anchor;
- elemindx = lvscan->elemcnt++; /* Note post increment so elemindx has minus-one value */
- if (ARY_SCNCNTNR_MAX < elemindx)
- { /* Present block is full so allocate a new one and chain it on */
- lvscan->elemcnt--; /* New element ended up not being in that block.. */
- newlvscan = (lvscan_blk *)malloc(SIZEOF(lvscan_blk));
- newlvscan->next = lvscan;
- newlvscan->elemcnt = 1; /* Going to use first one *now* */
- elemindx = 0;
- *lvscan_anchor = newlvscan;
- lvscan = newlvscan;
- }
- assert((ARY_SCNCNTNR_MAX >= elemindx) && (0 <= elemindx));
- lvscan->ary_scncntnr[elemindx] = curr_lv;
- }
}
} else
{
@@ -481,21 +439,23 @@ int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, lvsc
assert(NULL == LV_CHILD(save_lv));
assert(!save_lv->tp_var->var_cloned);
/* We know that the subscript array underneath curr_lv did not change since saving it into save_lv. But the
- * unsubscripted lv could have changed (have no way of checking if that is the case) so restore it unconditionally.
+ * unsubscripted lv could have changed (have no way of checking if that is the case) so restore it (just its
+ * value) unconditionally.
*/
curr_lv->v = save_lv->v;
/* No need to copy "save_lv->ptrs" as "ptrs" contains 2 fields both of which are already correct in "curr_lv" */
assert(save_lv->ptrs.val_ent.parent.sym == curr_lv->ptrs.val_ent.parent.sym);
assert(NULL == save_lv->ptrs.val_ent.children);
/* No need to copy "save_lv->stats" as "curr_lv->stats" is more uptodate */
- assert(save_lv->has_aliascont == curr_lv->has_aliascont); /* no need to copy this field */
- assert(save_lv->lvmon_mark == curr_lv->lvmon_mark); /* no need to copy this field */
- assert(save_lv->tp_var == curr_lv->tp_var); /* no need to copy this field */
+ assert(save_lv->has_aliascont == curr_lv->has_aliascont); /* No need to copy this field */
+ assert(save_lv->lvmon_mark == curr_lv->lvmon_mark); /* No need to copy this field */
+ assert(save_lv->tp_var == curr_lv->tp_var); /* No need to copy this field */
}
- if (NULL == lvscan_anchor)
+ if (clearTStartCycle)
/* Means this is completely unwinding a nested level so we need to reset the tstartcycle in this
* lvval so it gets handled correctly when this lv is encountered again after the restart completes.
*/
curr_lv->stats.tstartcycle = 0;
+ DBGRFCT((stderr, "tp_unwind_restlv: Complete (returning)\n"));
return 0;
}
diff --git a/sr_port/tp_unwind.h b/sr_port/tp_unwind.h
index 6057797..c5c3206 100644
--- a/sr_port/tp_unwind.h
+++ b/sr_port/tp_unwind.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,26 +19,7 @@ enum tp_unwind_invocation
RESTART_INVOCATION
};
-/* Array size to hold post unwind restored lv_vals to scan for containers differs between
- pro and dbg builds. For dbg, we want to exercise the code where more than one of the
- blocks is being processed but for production, we size the array where more than the
- one allocated in automatic storage would be "unusual".
-*/
-#ifdef DEBUG
-# define ARY_SCNCNTNR_DIM 1
-#else
-# define ARY_SCNCNTNR_DIM 28
-#endif
-#define ARY_SCNCNTNR_MAX (ARY_SCNCNTNR_DIM - 1)
-
-typedef struct post_restore_lvscan_struct
-{
- struct post_restore_lvscan_struct *next;
- lv_val *ary_scncntnr[ARY_SCNCNTNR_DIM];
- int elemcnt;
-} lvscan_blk;
-
void tp_unwind(uint4 newlevel, enum tp_unwind_invocation, int *tprestart_rc);
-int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, lvscan_blk **lvscan_anchor, int *tprestart_lc);
+int tp_unwind_restlv(lv_val *curr_lv, lv_val *save_lv, tp_var *restore_ent, boolean_t clearTStartCycle, int *tprestart_lc);
#endif
diff --git a/sr_port/trim.mpt b/sr_port/trim.mpt
index b5604d0..59cd148 100644
--- a/sr_port/trim.mpt
+++ b/sr_port/trim.mpt
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2012 Fidelity Information Services, Inc. ;
+; Copyright 2012, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -8,17 +8,21 @@
; the license, please stop and do not read further. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-%TRIM ; routine to strip of leading and trailing spaces/tabs
- for quit:$zeof read line write !,$$FUNC(line),!
+%TRIM ; routine to strip of leading and trailing characters; defaulting to spaces and tabs
+ for read line quit:$zeof write $$FUNC(line),!
quit
-FUNC(s) quit $$L($$R(s))
+FUNC(s,ch)
+ set:'$length($get(ch)) ch=$char(9,32)
+ quit $$L($$R(s,ch),ch)
-L(s) new i,l,tmp
- set l=$length(s)
- for set tmp=$extract(s,$increment(i)) quit:" "'=tmp&($c(9)'=tmp)!'$length(tmp)
- quit $extract(s,i,$length(s))
+L(s,ch) new i,len,tmp
+ set:'$length($get(ch)) ch=$char(9,32)
+ set len=$length(s)
+ for i=1:1:len+1 quit:ch'[$extract(s,i)
+ quit $extract(s,i,len)
-R(s) new i,l,tmp
- set i=$length(s)+1 for set tmp=$extract(s,$increment(i,-1)) quit:" "'=tmp&($c(9)'=tmp)!'i
+R(s,ch) new i,tmp
+ set:'$length($get(ch)) ch=$c(9,32)
+ for i=$length(s):-1:0 quit:ch'[$extract(s,i)
quit $extract(s,1,i)
diff --git a/sr_port/unw_mv_ent.c b/sr_port/unw_mv_ent.c
index 7f84895..8430a07 100644
--- a/sr_port/unw_mv_ent.c
+++ b/sr_port/unw_mv_ent.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -59,7 +59,6 @@
GBLREF symval *curr_symval;
GBLREF boolean_t dollar_truth;
-GBLREF lv_val *active_lv;
GBLREF gv_key *gv_currkey;
GBLREF gv_namehead *gv_target;
GBLREF gd_addr *gd_header;
@@ -123,7 +122,8 @@ void unw_mv_ent(mv_stent *mv_st_ent)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful, clear active_lv to avoid cleanup problems */
+ SET_ACTIVE_LV(NULL, TRUE, actlv_unw_mv_ent); /* If we get here, subscript set was successful.
+ * Clear active_lv to avoid later cleanup issues */
switch (mv_st_ent->mv_st_type)
{
case MVST_MSAV:
@@ -209,7 +209,7 @@ void unw_mv_ent(mv_stent *mv_st_ent)
lvval_ptr = (lv_val *)hte->value;
assert(lvval_ptr);
DECR_CREFCNT(lvval_ptr);
- assert(1 < lvval_ptr->stats.trefcnt);
+ assert(1 <= lvval_ptr->stats.trefcnt);
DECR_BASE_REF_NOSYM(lvval_ptr, TRUE);
xnewvarnext = xnewvar->next;
xnewvar->next = xnewvar_anchor;
diff --git a/sr_port/unw_retarg.c b/sr_port/unw_retarg.c
index 74e1ecc..04d8559 100644
--- a/sr_port/unw_retarg.c
+++ b/sr_port/unw_retarg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,6 +13,7 @@
#include "gtm_stdio.h"
+#include "gtmio.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "mv_stent.h"
@@ -70,7 +71,7 @@ int unw_retarg(mval *src, boolean_t alias_return)
alias_retarg = NULL;
DBGEHND_ONLY(prevfp = frame_pointer);
if (tp_pointer && tp_pointer->fp <= frame_pointer)
- rts_error(VARLSTCNT(1) ERR_TPQUIT);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TPQUIT);
assert(msp <= stackbase && msp > stacktop);
assert(mv_chain <= (mv_stent *)stackbase && mv_chain > (mv_stent *)stacktop);
assert(frame_pointer <= (stack_frame *)stackbase && frame_pointer > (stack_frame *)stacktop);
@@ -85,43 +86,44 @@ int unw_retarg(mval *src, boolean_t alias_return)
ret_value = *src;
ret_value.mvtype &= ~MV_ALIASCONT; /* Make sure alias container of regular return does not propagate */
} else
- { /* QUIT *var or *var(indx..) syntax was used - see which one it was */
- assert(NULL != src);
- srclv = (lv_val *)src; /* Since can never be an expression, this relationship is guaranteed */
- if (!LV_IS_BASE_VAR(srclv))
- { /* Have a potential container var - verify */
- if (!(MV_ALIASCONT & srclv->v.mvtype))
- rts_error(VARLSTCNT(1) ERR_ALIASEXPECTED);
- ret_value = *src;
- srclvc = (lv_val *)srclv->v.str.addr;
- assert(LV_IS_BASE_VAR(srclvc)); /* Verify base var */
- assert(srclvc->stats.trefcnt >= srclvc->stats.crefcnt);
- assert(1 <= srclvc->stats.crefcnt); /* Verify is existing container ref */
- base_lv = LV_GET_BASE_VAR(srclv);
- symlv = LV_GET_SYMVAL(base_lv);
- symlvc = LV_GET_SYMVAL(srclvc);
- MARK_ALIAS_ACTIVE(MIN(symlv->symvlvl, symlvc->symvlvl));
- DBGRFCT((stderr, "unw_retarg: Returning alias container 0x"lvaddr" pointing to 0x"lvaddr" to caller\n",
- src, srclvc));
- } else
- { /* Creating a new alias - create a container to pass back */
- memcpy(&ret_value, &literal_null, SIZEOF(mval));
- ret_value.mvtype |= MV_ALIASCONT;
- ret_value.str.addr = (char *)srclv;
- srclvc = srclv;
- MARK_ALIAS_ACTIVE(LV_SYMVAL(srclv)->symvlvl);
- DBGRFCT((stderr, "unw_retarg: Returning alias 0x"lvaddr" to caller\n", srclvc));
- }
- INCR_TREFCNT(srclvc);
- INCR_CREFCNT(srclvc); /* This increment will be reversed if this container gets put into an alias */
- /* We have a slight chicken-and-egg problem now. The mv_stent unwind loop below may pop a symbol table thus
+ { /* QUIT *var or *var(indx..) syntax was used.
+ * We have a slight chicken-and-egg problem now. The mv_stent unwind loop below may pop a symbol table thus
* destroying the lv_val in our container. To prevent this, we need to locate the parm block before the symval is
* unwound and set the return value and alias_retarg appropriately so the symtab unwind logic called by
* unw_mv_ent() can work any necessary relocation magic on the return var.
*/
trg = get_ret_targ(NULL);
if (NULL != trg)
- {
+ { /* QUIT *var or *var(indx..) syntax was used - see which one it was */
+ assert(NULL != src);
+ srclv = (lv_val *)src; /* Since can never be an expression, this relationship is guaranteed */
+ if (!LV_IS_BASE_VAR(srclv))
+ { /* Have a potential container var - verify */
+ if (!(MV_ALIASCONT & srclv->v.mvtype))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ALIASEXPECTED);
+ ret_value = *src;
+ srclvc = (lv_val *)srclv->v.str.addr;
+ assert(LV_IS_BASE_VAR(srclvc)); /* Verify base var */
+ assert(srclvc->stats.trefcnt >= srclvc->stats.crefcnt);
+ assert(1 <= srclvc->stats.crefcnt); /* Verify is existing container ref */
+ base_lv = LV_GET_BASE_VAR(srclv);
+ symlv = LV_GET_SYMVAL(base_lv);
+ symlvc = LV_GET_SYMVAL(srclvc);
+ MARK_ALIAS_ACTIVE(MIN(symlv->symvlvl, symlvc->symvlvl));
+ DBGRFCT((stderr,
+ "unw_retarg: Returning alias container 0x"lvaddr" pointing to 0x"lvaddr" to caller\n",
+ src, srclvc));
+ } else
+ { /* Creating a new alias - create a container to pass back */
+ memcpy(&ret_value, &literal_null, SIZEOF(mval));
+ ret_value.mvtype |= MV_ALIASCONT;
+ ret_value.str.addr = (char *)srclv;
+ srclvc = srclv;
+ MARK_ALIAS_ACTIVE(LV_SYMVAL(srclv)->symvlvl);
+ DBGRFCT((stderr, "unw_retarg: Returning alias 0x"lvaddr" to caller\n", srclvc));
+ }
+ INCR_TREFCNT(srclvc);
+ INCR_CREFCNT(srclvc); /* This increment will be reversed if this container gets put into an alias */
*trg = ret_value;
alias_retarg = trg;
got_ret_target = TRUE;
@@ -153,7 +155,7 @@ int unw_retarg(mval *src, boolean_t alias_return)
}
/* do not throw an error if return value is expected from a non-extrinsic, but dollar_zquit_anyway is true */
if (!dollar_zquit_anyway && !got_ret_target)
- rts_error(VARLSTCNT(1) ERR_NOTEXTRINSIC); /* This routine was not invoked as an extrinsic function */
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOTEXTRINSIC); /* Routine not invoked as an extrinsic function */
/* Note that error_ret() should be invoked only after the rts_error() of TPQUIT and NOTEXTRINSIC.
* This is so the TPQUIT/NOTEXTRINSIC error gets noted down in $ECODE (which wont happen if error_ret() is called before).
*/
@@ -169,7 +171,7 @@ int unw_retarg(mval *src, boolean_t alias_return)
if ((NULL != zyerr_frame) && (frame_pointer > zyerr_frame))
zyerr_frame = NULL;
if (!frame_pointer)
- rts_error(VARLSTCNT(1) ERR_STACKUNDERFLO);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_STACKUNDERFLO);
assert(frame_pointer >= (stack_frame *)msp);
/* ensuring that trg is not NULL */
if (!dollar_zquit_anyway || trg)
diff --git a/sr_port/updhelper_reader.c b/sr_port/updhelper_reader.c
index ad4102e..cb43a0d 100644
--- a/sr_port/updhelper_reader.c
+++ b/sr_port/updhelper_reader.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2005, 2013 Fidelity Information Services, Inc. *
+ * Copyright 2005, 2014 Fidelity Information Services, Inc. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -79,11 +79,15 @@
#endif
#ifdef GTM_TRIGGER
-#include <rtnhdr.h> /* for rtn_tabent in gv_trigger.h */
+#include <rtnhdr.h> /* for rtn_tabent in gv_trigger.h */
#include "gv_trigger.h"
#include "tp_set_sgm.h"
#endif
+#ifdef DEBUG
+#include "repl_filter.h" /* needed by an assert in UPD_GV_BIND_NAME_APPROPRIATE macro */
+#endif
+
#define MAX_LCNT 100
GBLREF void (*call_on_signal)();
diff --git a/sr_port/updproc.c b/sr_port/updproc.c
index 1781596..adfa376 100644
--- a/sr_port/updproc.c
+++ b/sr_port/updproc.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -63,6 +63,11 @@
#include <rtnhdr.h> /* for rtn_tabent in gv_trigger.h */
#include "gv_trigger.h"
#include "targ_alloc.h"
+#include "trigger.h"
+#include "hashtab_str.h"
+#include "io.h"
+#include "trigger_update_protos.h"
+#include "util.h"
#endif
#ifdef VMS
#include <fab.h>
@@ -100,6 +105,9 @@
#include "tp_frame.h"
#include "gvcst_jrt_null.h" /* for gvcst_jrt_null prototype */
#include "preemptive_db_clnup.h"
+#ifdef DEBUG
+#include "repl_filter.h" /* needed by an assert in UPD_GV_BIND_NAME_APPROPRIATE macro */
+#endif
#define UPDPROC_WAIT_FOR_READJNLSEQNO 100 /* ms */
#define UPDPROC_WAIT_FOR_STARTJNLSEQNO 100 /* ms */
@@ -141,6 +149,7 @@ DEBUG_ONLY(GBLREF ch_ret_type (*ch_at_trigger_init)();)
GBLREF int tprestart_state; /* When triggers restart, multiple states possible. See tp_restart.h */
GBLREF dollar_ecode_type dollar_ecode; /* structure containing $ECODE related information */
GBLREF mval dollar_ztwormhole;
+GBLREF boolean_t dollar_ztrigger_invoked;
#endif
GBLREF boolean_t skip_dbtriggers;
GBLREF gv_namehead *gv_target;
@@ -293,6 +302,18 @@ CONDITION_HANDLER(updproc_ch)
# error unsupported platform
# endif
{
+ /* It is possible that dollar_tlevel at the time of the ESTABLISH of updproc_ch was 0
+ * and the op_tstart happened inside updproc_actions and later as part of op_tcommit a
+ * restart happens which brings dollar_tlevel to 1 before coming here. Even though
+ * dollar_tlevel before the UNWIND done below is not the same as that at ESTABLISH time,
+ * the flow of control happens correctly so op_tstart is not done again but everything
+ * else in this transaction is re-executed. So treat this as an exception and adjust
+ * active_ch->dollar_tlevel so it is in sync with the current dollar_tlevel. This prevents
+ * an assert failure in UNWIND. START_CH would have done a active_ch-- so we need a
+ * active_ch[1] to get at the desired active_ch.
+ */
+ UNIX_ONLY(assert(active_ch[1].dollar_tlevel <= dollar_tlevel);)
+ UNIX_ONLY(DEBUG_ONLY(active_ch[1].dollar_tlevel = dollar_tlevel;))
UNWIND(NULL, NULL);
}
# ifdef VMS
@@ -321,6 +342,13 @@ CONDITION_HANDLER(updproc_ch)
preemptive_db_clnup(SEVERITY);
assert(INVALID_GV_TARGET == reset_gv_target);
set_onln_rlbk_flg = TRUE;
+ /* Just like the UNWIND done above in the tprestart case, this is a case where an online rollback is signaled
+ * inside updproc_actions. The ESTABLISH might have been done many transactions back as part of a restart or
+ * as part of an online rollback or as part of a bad-trans. So the dollar_tlevel at the ESTABLISH time could
+ * be 0 or non-zero and has no relation to the dollar_tlevel currently. So just fix active_ch->dollar_tlevel
+ * before the UNWIND call to avoid any dollar_tlevel related assert failures.
+ */
+ UNIX_ONLY(DEBUG_ONLY(active_ch[1].dollar_tlevel = dollar_tlevel;))
UNWIND(NULL, NULL);
}
# endif
@@ -982,7 +1010,7 @@ void updproc_actions(gld_dbname_list *gld_db_files)
bad_trans_type = upd_bad_key;
assert(FALSE);
}
- } else if (IS_ZTWORM(rectype))
+ } else if (IS_ZTWORM(rectype) || IS_LGTRIG(rectype))
{
assert(IS_FENCED(rectype));
assert(IS_TP(rectype));
@@ -990,7 +1018,9 @@ void updproc_actions(gld_dbname_list *gld_db_files)
assert(0 == tcom_num);
if (0 > tupd_num || 0 != tcom_num)
{
- bad_trans_type = upd_fence_bad_ztworm_t_num;
+ bad_trans_type = IS_ZTWORM(rectype)
+ ? upd_fence_bad_ztworm_t_num
+ : upd_fence_bad_lgtrig_t_num;
assert(FALSE);
} else if (IS_TUPD(rectype))
{
@@ -1252,14 +1282,34 @@ void updproc_actions(gld_dbname_list *gld_db_files)
csa->n_pre_read_trigger--;
disk_blk_read = FALSE;
}
- } else if (IS_ZTWORM(rectype))
+ }
+# ifdef GTM_TRIGGER
+ else if (IS_ZTWORM(rectype))
{
assert(dollar_tlevel); /* op_tstart should already have been done */
val_mv.mvtype = MV_STR;
val_mv.str.len = rec->jrec_ztworm.ztworm_str.length;
val_mv.str.addr = &rec->jrec_ztworm.ztworm_str.text[0];
op_svput(SV_ZTWORMHOLE, &val_mv);
+ } else if (IS_LGTRIG(rectype))
+ {
+ int i;
+ boolean_t trigger_status;
+ uint4 trig_stats[NUM_STATS];
+
+ assert(dollar_tlevel);
+ for (i = 0; NUM_STATS > i; i++)
+ trig_stats[i] = 0;
+ /* clear any pending data in util_outptr as trigger_update_rec will otherwise append to it */
+ util_out_print(NULL, RESET);
+ dollar_ztrigger_invoked = TRUE; /* needed to ensure later SET/KILLs done in this TP transaction
+ * read triggers installed by the below trigger_update_rec call.
+ */
+ trigger_status = trigger_update_rec(rec->jrec_lgtrig.lgtrig_str.text,
+ rec->jrec_lgtrig.lgtrig_str.length, TRUE, trig_stats, NULL, NULL);
+ assert(TRIG_SUCCESS == trigger_status);
}
+# endif
}
if (upd_good_record != bad_trans_type)
{
diff --git a/sr_port/updproc.h b/sr_port/updproc.h
index 6134e84..5fd830b 100644
--- a/sr_port/updproc.h
+++ b/sr_port/updproc.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -30,6 +30,7 @@ enum upd_bad_trans_type
upd_bad_histinfo_start_seqno1,
upd_bad_histinfo_start_seqno2,
upd_fence_bad_ztworm_t_num,
+ upd_fence_bad_lgtrig_t_num,
upd_bad_key
};
@@ -47,8 +48,11 @@ enum upd_bad_trans_type
\
if (IS_MNAME_HASHT_GBLNAME(GVNAME.var_name)) \
{ /* gbl is ^#t. In this case, do special processing. Look at the first subscript and \
- * bind to the region mapped to by that global name (not ^#t). \
+ * bind to the region mapped to by that global name (not ^#t). Also since V62 will \
+ * never receive ^#t records from V62 source (it will receive TLGTRIG/ULGTRIG logical \
+ * journal records only) assert accordingly. \
*/ \
+ assert(V24_JNL_VER > gtmrecv_local->remote_side.jnl_ver); \
tr_ptr = KEY; /* Skip to the first subscript */ \
tr_len = STRLEN(KEY); /* Only want length to first 0, not entire length */ \
assert(tr_len < KEYLEN); /* If ^#t, there has to be a subscript */ \
@@ -64,8 +68,7 @@ enum upd_bad_trans_type
GV_BIND_NAME_ONLY(GD_HEADER, &gvname1, GVNH_REG); \
csa = cs_addrs; \
SET_GVTARGET_TO_HASHT_GBL(csa); \
- if (!dollar_ztrigger_invoked) \
- dollar_ztrigger_invoked = TRUE; \
+ dollar_ztrigger_invoked = TRUE; \
csa->incr_db_trigger_cycle = TRUE; \
csa->db_dztrigger_cycle++; \
} else \
diff --git a/sr_port/updproc_end.c b/sr_port/updproc_end.c
index c214371..5820630 100644
--- a/sr_port/updproc_end.c
+++ b/sr_port/updproc_end.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,9 +24,9 @@
#ifdef UNIX
#include "gtm_ipc.h"
+#include <gtm_un.h>
#include <sys/sem.h>
#include <sys/shm.h>
-#include <sys/un.h>
#ifndef __MVS__
#include <sys/param.h>
#endif
@@ -121,7 +121,7 @@ void updproc_stop(boolean_t exit)
repl_log(updproc_log_fp, TRUE, TRUE, "REPL INFO - Current Update process Read Seqno : %llu\n", log_seqno1);
repl_log(updproc_log_fp, TRUE, TRUE, "REPL INFO - Current Receive Pool Seqno : %llu\n", log_seqno);
# ifdef UNIX
- if (!ANTICIPATORY_FREEZE_AVAILABLE)
+ if (!INST_FREEZE_ON_ERROR_POLICY)
{
mutex_cleanup(jnlpool.jnlpool_dummy_reg);
JNLPOOL_SHMDT(status, save_errno);
diff --git a/sr_port/util_ch.c b/sr_port/util_ch.c
index 1064eec..75ba92d 100644
--- a/sr_port/util_ch.c
+++ b/sr_port/util_ch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -30,7 +30,7 @@ error_def(ERR_VMSMEMORY);
CONDITION_HANDLER(util_ch)
{
- START_CH(SIGNAL != ERR_CTRLC);
+ START_CH(TRUE);
if (DUMPABLE)
NEXTCH;
diff --git a/sr_port/view_arg_convert.c b/sr_port/view_arg_convert.c
index dc5cc8b..52d1542 100644
--- a/sr_port/view_arg_convert.c
+++ b/sr_port/view_arg_convert.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -118,6 +118,8 @@ void view_arg_convert(viewtab_entry *vtp, int vtp_parm, mval *parm, viewparm *pa
if (NULL == parm)
rts_error_csa(CSA_ARG(NULL)
VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
+ if (!parm->str.len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOTGBL, 2, parm->str.len, NULL);
if (!gd_header) /* IF GD_HEADER ==0 THEN OPEN GBLDIR */
gvinit();
c = (unsigned char *)parm->str.addr;
diff --git a/sr_port/viewtab.h b/sr_port/viewtab.h
index 14e6571..f80f090 100644
--- a/sr_port/viewtab.h
+++ b/sr_port/viewtab.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -17,12 +17,13 @@ VIEWTAB("0", VTP_NULL, VTK_GDSCERT0, MV_STR),
VIEWTAB("1", VTP_NULL, VTK_GDSCERT1, MV_STR),
VIEWTAB("BADCHAR", VTP_NULL, VTK_BADCHAR, MV_NM),
VIEWTAB("BREAKMSG", VTP_NULL | VTP_VALUE, VTK_BREAKMSG, MV_NM),
+VIEWTAB("DBFLUSH", VTP_DBREGION | VTP_NULL, VTK_DBFLUSH, MV_STR),
+VIEWTAB("DBSYNC", VTP_DBREGION | VTP_NULL, VTK_DBSYNC, MV_STR),
VIEWTAB("DEBUG1", VTP_VALUE | VTP_NULL, VTK_DEBUG1, MV_STR),
VIEWTAB("DEBUG2", VTP_VALUE | VTP_NULL, VTK_DEBUG2, MV_STR),
VIEWTAB("DEBUG3", VTP_VALUE | VTP_NULL, VTK_DEBUG3, MV_STR),
VIEWTAB("DEBUG4", VTP_VALUE | VTP_NULL, VTK_DEBUG4, MV_STR),
-VIEWTAB("DBFLUSH", VTP_DBREGION | VTP_NULL, VTK_DBFLUSH, MV_STR),
-VIEWTAB("DBSYNC", VTP_DBREGION | VTP_NULL, VTK_DBSYNC, MV_STR),
+VIEWTAB("DMTERM", VTP_NULL, VTK_DMTERM, MV_NM),
VIEWTAB("EPOCH", VTP_DBREGION | VTP_NULL, VTK_EPOCH, MV_STR),
VIEWTAB("FILL_FACTOR", VTP_VALUE | VTP_NULL, VTK_FILLFACTOR, MV_NM),
VIEWTAB("FLUSH", VTP_DBREGION | VTP_NULL, VTK_FLUSH, MV_STR),
@@ -73,6 +74,7 @@ VIEWTAB("LV_REHASH", VTP_NULL, VTK_LVREHASH, MV_NM),
VIEWTAB("MAX_SOCKETS", VTP_NULL, VTK_MAXSOCKETS, MV_NM),
VIEWTAB("NEVERLVNULLSUBS", VTP_NULL, VTK_NEVERLVNULLSUBS, MV_NM),
VIEWTAB("NOBADCHAR", VTP_NULL, VTK_NOBADCHAR, MV_NM),
+VIEWTAB("NODMTERM", VTP_NULL, VTK_NODMTERM, MV_NM),
VIEWTAB("NOFULL_BOOLEAN", VTP_NULL, VTK_NOFULLBOOL, MV_STR),
VIEWTAB("NOISOLATION", VTP_NULL | VTP_DBKEYLIST, VTK_NOISOLATION, MV_NM),
VIEWTAB("NOLOGTPRESTART", VTP_NULL, VTK_NOLOGTPRESTART, MV_NM),
@@ -86,6 +88,9 @@ VIEWTAB("PROBECRIT", VTP_DBREGION, VTK_PROBECRIT, MV_NM),
VIEWTAB("RCHITS", VTP_NULL, VTK_RCHITS, MV_NM),
VIEWTAB("RCMISSES", VTP_NULL, VTK_RCMISSES, MV_NM),
VIEWTAB("RCSIZE", VTP_NULL, VTK_RCSIZE, MV_NM),
+#if defined(DEBUG) && defined(USHBIN_SUPPORTED)
+VIEWTAB("RCTLDUMP", VTP_NULL, VTK_RCTLDUMP, MV_STR),
+#endif
VIEWTAB("REGION", VTP_DBKEY, VTK_REGION, MV_STR),
VIEWTAB("RESETGVSTATS", VTP_NULL, VTK_RESETGVSTATS, MV_STR),
VIEWTAB("RTNCHECKSUM", VTP_RTNAME, VTK_RTNCHECKSUM, MV_STR),
diff --git a/sr_port/wbox_test_init.h b/sr_port/wbox_test_init.h
index c95a165..5d3a11c 100644
--- a/sr_port/wbox_test_init.h
+++ b/sr_port/wbox_test_init.h
@@ -1,7 +1,7 @@
/****************************************************************
* *
- * Copyright 2005, 2013 Fidelity Information Services, Inc *
+ * Copyright 2005, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -99,7 +99,7 @@ typedef enum {
WBTEST_HOLD_CRIT_TILL_LCKALERT, /* 66 : Grab and hold crit until 15 seconds past what triggers a lock alert message
* which should invoke a mutex salvage */
WBTEST_OPER_LOG_MSG, /* 67 : send message to operator log */
- WBTEST_UNUSED_1, /* 68 : */
+ WBTEST_FAKE_BIG_EXTRACT, /* 68 : fake large increase in EXTRACT record count to show it doesn't overflow */
/* Begin ANTIFREEZE related white box test cases */
WBTEST_ANTIFREEZE_JNLCLOSE, /* 69 : */
WBTEST_ANTIFREEZE_DBBMLCORRUPT, /* 70 : */
@@ -135,7 +135,11 @@ typedef enum {
WBTEST_HOLD_FTOK_UNTIL_BYPASS, /* 96 : Hold the ftok semaphore until another process comes and bypasses it */
WBTEST_SLEEP_IN_WCS_WTSTART, /* 97 : Sleep in one of the predetermined places inside wcs_wtstart.c */
WBTEST_SETITIMER_ERROR, /* 98 : Simulate an error return from setitimer in gt_timers.c */
- WBTEST_HOLD_GTMSOURCE_SRV_LATCH /* 99 : Hold the source server latch until rollback process issues a SIGCONT */
+ WBTEST_HOLD_GTMSOURCE_SRV_LATCH, /* 99 : Hold the source server latch until rollback process issues a SIGCONT */
+ WBTEST_KILL_ROLLBACK, /* 100: Kill in the middle of rollback */
+ WBTEST_INFO_HUB_SEND_ZMESS, /* 101 : Print messages triggered via ZMESSAGE to the syslog */
+ WBTEST_SKIP_CORE_FOR_MEMORY_ERROR, /* 102 : Do not generate core file in case of GTM-E-MEMORY fatal error */
+ WBTEST_EXTFILTER_INDUCE_ERROR, /* 103 : Do not assert in case of external filter error (test induces that) */
/* Note 1: when adding new white box test cases, please make use of WBTEST_ENABLED and WBTEST_ASSIGN_ONLY (defined below)
* whenever applicable
* Note 2: when adding a new white box test case, see if an existing WBTEST_UNUSED* slot can be levereged.
diff --git a/sr_port/wcs_recover.c b/sr_port/wcs_recover.c
index 671f698..be0ea08 100644
--- a/sr_port/wcs_recover.c
+++ b/sr_port/wcs_recover.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -117,6 +117,17 @@ error_def(ERR_STOPTIMEOUT);
error_def(ERR_SYSCALL);
error_def(ERR_TEXT);
+#define BT_NOT_NULL(BT, CR, CSA, REG) \
+{ \
+ if (NULL == BT) \
+ { /* NULL value is only possible if wcs_get_space in bt_put fails */ \
+ send_msg_csa(CSA_ARG(CSA) VARLSTCNT(13) ERR_DBCRERR, 11, DB_LEN_STR(REG), \
+ CR, CR->blk, RTS_ERROR_TEXT("Non-zero bt"), BT, TRUE, CALLFROM); \
+ assert(FALSE); \
+ continue; \
+ } \
+}
+
void wcs_recover(gd_region *reg)
{
bt_rec_ptr_t bt;
@@ -387,8 +398,12 @@ void wcs_recover(gd_region *reg)
* all following cr's. If r_epid is 0 and also read in progress, we identify
* this as corruption and fixup up this cr and proceed to the next cr.
*/
- assert(FALSE || (WBTEST_CRASH_SHUTDOWN_EXPECTED == gtm_white_box_test_case_number));
- assertpro((0 == r_epid) || (epid == r_epid));
+ assert(WBTEST_CRASH_SHUTDOWN_EXPECTED == gtm_white_box_test_case_number);
+ if (!((0 == r_epid) || (epid == r_epid)))
+ {
+ send_msg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_INVALIDRIP, 2, DB_LEN_STR(reg));
+ assert(FALSE);
+ }
/* process still active but not playing fair or cache is corrupted */
GET_C_STACK_FROM_SCRIPT("BUFRDTIMEOUT", process_id, r_epid, TWICE);
send_msg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_BUFRDTIMEOUT, 6, process_id, cr->blk, cr, r_epid,
@@ -426,10 +441,14 @@ void wcs_recover(gd_region *reg)
epid = cr->epid;
else if (BUF_OWNER_STUCK < lcnt)
{
- assertpro((0 == cr->epid) || (epid == cr->epid));
+ if (!((0 == cr->epid) || (epid == cr->epid)))
+ {
+ send_msg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_INVALIDRIP, 2, DB_LEN_STR(reg));
+ assert(FALSE);
+ }
if (0 != epid)
{ /* process still active, but not playing fair */
- send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_STOPTIMEOUT, 3, epid,
+ send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_STOPTIMEOUT, 3, cr->epid,
DB_LEN_STR(reg));
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2,
LEN_AND_LIT("Buffer forcibly seized"));
@@ -493,13 +512,14 @@ void wcs_recover(gd_region *reg)
change_bmm = TRUE;
}
} /* end of bitmap processing */
- if (certify_all_blocks)
- cert_blk(reg, cr->blk, (blk_hdr_ptr_t)GDS_REL2ABS(cr->buffaddr), 0, TRUE);/* assertpro() on error */
+ if (!cert_blk(reg, cr->blk, (blk_hdr_ptr_t)GDS_REL2ABS(cr->buffaddr), 0, FALSE))
+ { /* always check the block and return - no assertpro, so last argument is FALSE */
+ send_msg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_DBDANGER, 5, cr->data_invalid, cr->data_invalid,
+ DB_LEN_STR(reg), cr->blk);
+ assert(gtm_white_box_test_case_enabled);
+ }
bt = bt_put(reg, cr->blk);
- /* NULL value for 'bt' is only possible if wcs_get_space in bt_put fails which is impossible here since we
- * have called bt_refresh above. Confrim this in the below assertpro().
- */
- assertpro(NULL != bt);
+ BT_NOT_NULL(bt, cr, csa, reg);
bt->killtn = csd->trans_hist.curr_tn; /* be safe; don't know when was last kill after recover */
if (CR_NOTVALID != bt->cache_index)
{ /* the bt already identifies another cache entry with this block */
@@ -633,7 +653,7 @@ void wcs_recover(gd_region *reg)
hq = (cache_que_head_ptr_t)(hash_hdr + (cr->blk % bt_buckets));
WRITE_LATCH_VAL(cr) = LATCH_SET;
bt = bt_put(reg, cr->blk);
- assertpro(NULL != bt); /* NULL value is only possible if wcs_get_space in bt_put fails */
+ BT_NOT_NULL(bt, cr, csa, reg);
bt->killtn = csd->trans_hist.curr_tn; /* be safe; don't know when was last kill after recover */
if (CR_NOTVALID == bt->cache_index)
{ /* no previous entry for this block; more recent cache record will twin when processed */
@@ -676,7 +696,7 @@ void wcs_recover(gd_region *reg)
if ((LATCH_SET > WRITE_LATCH_VAL(cr)) VMS_ONLY(|| (WRT_STRT_PNDNG == cr->iosb.cond)))
{ /* no process has an interest */
bt = bt_put(reg, cr->blk);
- assertpro(NULL != bt); /* NULL value is only possible if wcs_get_space in bt_put fails */
+ BT_NOT_NULL(bt, cr, csa, reg);
bt->killtn = csd->trans_hist.curr_tn; /* be safe; don't know when was last kill after recover */
if (CR_NOTVALID == bt->cache_index)
{ /* no previous entry for this block */
@@ -737,7 +757,7 @@ void wcs_recover(gd_region *reg)
UNIX_ONLY(WRITE_LATCH_VAL(cr) = LATCH_CLEAR;)
hq = (cache_que_head_ptr_t)(hash_hdr + (cr->blk % bt_buckets));
bt = bt_put(reg, cr->blk);
- assertpro(NULL != bt); /* NULL value is only possible if wcs_get_space in bt_put fails */
+ BT_NOT_NULL(bt, cr, csa, reg);
bt->killtn = csd->trans_hist.curr_tn; /* be safe; don't know when was last kill after recover */
if (CR_NOTVALID == bt->cache_index)
{ /* no previous entry for this block */
diff --git a/sr_port/xcmd.mpt b/sr_port/xcmd.mpt
index 9fbedd6..4b91afd 100644
--- a/sr_port/xcmd.mpt
+++ b/sr_port/xcmd.mpt
@@ -11,11 +11,11 @@
; Utility to execute a shell command and return a non-zero status on error
;
%XCMD ; Usage: mumps -run %XCMD '<string>'
- ;
- set $ETRAP="goto CLIERR^%XCMD"
- do ; protect %XCMD's error handler
- . new $ETRAP set $ETRAP="goto CLIERR^%XCMD"
- . xecute $zcmdline
+ ; If no $ETRAP defined, use CLIERR^%XCMD overriding a potential $ZTRAP error handler
+ if ""=$ETRAP new $ETRAP set $ETRAP="goto CLIERR^%XCMD"
+ new etrap set etrap=$ETRAP
+ ; Protect %XCMD's error handler by NEWing and SETing $ETRAP at the begining of the XECUTEd command
+ xecute "new $ETRAP set $ETRAP=etrap "_$zcmdline
quit
CLIERR
@@ -30,9 +30,10 @@ CLIERR
; Perform a given command on every line of input
;
LOOP ; Usage: mumps -run LOOP^%XCMD [--before=|<string>|] [--after=|<string>|] --xec=|<string>|
- set $ETRAP="do LOOPERR^%XCMD"
- new %cli,%l,%NR,%xcmd
- set %cli=$zcmdline
+ ; If no $ETRAP defined, use LOOPERR^%XCMD overriding a potential $ZTRAP error handler
+ if ""=$ETRAP new $ETRAP set $ETRAP="goto LOOPERR^%XCMD"
+ new %cli,%l,%NR,%xcmd,etrap
+ set %cli=$zcmdline,etrap=$ETRAP
for quit:'$$trimleadingstr(.%cli,"--") do ; process command line options
. if $$trimleadingstr(.%cli,"after=") set %xcmd("after")=$$trimleadingdelimstr(.%cli)
. else if $$trimleadingstr(.%cli,"before=") set %xcmd("before")=$$trimleadingdelimstr(.%cli)
@@ -42,16 +43,16 @@ LOOP ; Usage: mumps -run LOOP^%XCMD [--before=|<string>|] [--after=|<string>|] -
set:'$length($get(%xcmd("xec"))) $ecode=",U253,"
set:$length(%cli) $ecode=",U252,"
kill %cli
- do ; protect %XCMD's error handler
- . new $ETRAP set $ETRAP="do LOOPERR^%XCMD"
- . do cmd($get(%xcmd("before")),0,"")
- . for %NR=1:1 read %l quit:$zeof do cmd(%xcmd("xec"),%NR,%l)
- . do cmd($get(%xcmd("after")),%NR,%l)
+ do cmd($get(%xcmd("before")),0,"",etrap)
+ for %NR=1:1 read %l quit:$zeof do cmd(%xcmd("xec"),%NR,%l,etrap)
+ do cmd($get(%xcmd("after")),%NR,%l,etrap)
quit
-cmd(cmd,%NR,%l)
+cmd(cmd,%NR,%l,ltrap)
quit:$length(cmd)=0
- new %xcmd
+ ; Protect LOOP^%XCMD's internal variables %xcmd and etrap and $ETRAP from modification by the XECUTEd command
+ new %xcmd,etrap,$ETRAP
+ set $ETRAP=ltrap
xecute cmd
quit
diff --git a/sr_port/xfer.h b/sr_port/xfer.h
index 7471c41..bf8e25e 100644
--- a/sr_port/xfer.h
+++ b/sr_port/xfer.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -128,7 +128,11 @@ XFER(xf_rdone, op_rdone),
XFER(xf_readfl, op_readfl),
XFER(xf_rhdaddr, op_rhdaddr),
XFER(xf_setpiece, op_setpiece),
+#ifdef USHBIN_SUPPORTED
+XFER(xf_setzbrk, opp_setzbrk), /* need assembly wrapper to handle shared routines - need to burn return pc */
+#else
XFER(xf_setzbrk, op_setzbrk),
+#endif
XFER(xf_svput, op_svput),
XFER(xf_view, op_view),
XFER(xf_xnew, opp_xnew),
@@ -302,4 +306,15 @@ XFER(xf_indmerge2, op_indmerge2),
XFER(xf_fnzpeek, op_fnzpeek),
#endif
XFER(xf_litc, op_litc),
-XFER(xf_stolitc, op_stolitc)
+XFER(xf_stolitc, op_stolitc),
+XFER(xf_fnzsocket, op_fnzsocket)
+#ifdef UNIX
+,
+XFER(xf_fnzsyslog, op_fnzsyslog),
+XFER(xf_zrupdate, op_zrupdate)
+#endif
+#ifdef USHBIN_SUPPORTED
+,
+XFER(xf_rhd_ext, op_rhd_ext),
+XFER(xf_lab_ext, op_lab_ext)
+#endif
diff --git a/sr_port/xfer_enum.h b/sr_port/xfer_enum.h
index 54bd80f..b7c3c57 100644
--- a/sr_port/xfer_enum.h
+++ b/sr_port/xfer_enum.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2007 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,6 +11,18 @@
/* File modified by Hallgarth on 28-APR-1986 08:39:49.98 */
+/* Define some macros to allow conditional commas at the end of statements useful for when the last entry in the
+ * xfer table is surrounded by #ifdef. This is sort of like UNIX_ONLY_COMMA() except that macro drops the entire
+ * argument if not UNIX, not just the comma.
+ */
+#ifdef UNIX
+# define UNIX_COMMA(x) x,
+# define VMS_COMMA(x) x
+#else
+# define UNIX_COMMA(x) x
+# define VMS_COMMA(x) x,
+#endif
+
/* Declare all xf_* enumerators */
#ifndef XFER_ENUM_H
#define XFER_ENUM_H
diff --git a/sr_port/xfer_name.c b/sr_port/xfer_name.c
index 900e11a..0c33d8d 100644
--- a/sr_port/xfer_name.c
+++ b/sr_port/xfer_name.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2002 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,6 +11,8 @@
#include "mdef.h"
+#include "xfer_enum.h"
+
#define XFER(a,b) #a
LITDEF char *xfer_name[] =
diff --git a/sr_port/zbreak.h b/sr_port/zbreak.h
index 1da6f58..c68d0cd 100644
--- a/sr_port/zbreak.h
+++ b/sr_port/zbreak.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -50,6 +50,6 @@ zbrk_struct *zr_get_free(z_records *zrecs, zb_code *addr);
void zr_init(z_records *zrecs, int4 count);
void zr_put_free(z_records *zrecs, zbrk_struct *z_ptr);
zb_code *find_line_call(void *addr);
-void zr_remove(rhdtyp *rtn, boolean_t notify_is_trigger);
+void zr_remove_zbrks(rhdtyp *rtn, boolean_t notify_is_trigger);
#endif /* ZBREAK_H_INCLUDED */
diff --git a/sr_port/zlput_rname.c b/sr_port/zlput_rname.c
index cba8f6b..e766bb1 100644
--- a/sr_port/zlput_rname.c
+++ b/sr_port/zlput_rname.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,6 +11,12 @@
#include "mdef.h"
+#include <sys/types.h>
+#include <sys/mman.h>
+#ifdef UNIX
+#include <sys/shm.h>
+#endif
+
#include "gtm_string.h"
#include "cmd_qlf.h"
#include <rtnhdr.h>
@@ -23,31 +29,34 @@
#include "min_max.h"
#include "stringpool.h"
#include "gtm_text_alloc.h"
+#ifdef USHBIN_SUPPORTED
+#include <incr_link_sp.h>
+#endif
+#include "zr_unlink_rtn.h"
#ifdef UNIX
#include "srcline.h"
#include "gtmlink.h"
#endif
#include "mmemory.h"
-STATICFNDCL boolean_t handle_active_old_versions(rhdtyp *old_rhead, rhdtyp *hdr);
-void zr_release(rhdtyp *old_rhead);
+STATICFNDCL boolean_t handle_active_old_versions(boolean_t *duplicated, rhdtyp *old_rhead, rhdtyp *hdr);
#define S_CUTOFF 7
#define FREE_RTNTBL_SPACE 17
-#define RTNTBL_EXP_MIN (SIZEOF(rtn_tabent) * FREE_RTNTBL_SPACE) /* never expand the routine name table by less than 17 entries */
-#define RTNTBL_EXP_MAX ((16 * 1024) + 1) /* never expand the routine name table by more than 16KB (at one time) */
+#define RTNTBL_EXP_MIN (SIZEOF(rtn_tabent) * FREE_RTNTBL_SPACE) /* Never expand the routine name table by less than 17 entries */
+#define RTNTBL_EXP_MAX ((16 * 1024) + 1) /* Never expand the routine name table by more than 16KB (at one time) */
GBLREF rtn_tabent *rtn_fst_table, *rtn_names, *rtn_names_end, *rtn_names_top;
GBLREF stack_frame *frame_pointer;
bool zlput_rname (rhdtyp *hdr)
{
- rhdtyp *old_rhead, *rhead, *prev_active;
+ rhdtyp *old_rhead, *rhead;
rtn_tabent *mid;
char *src, *new, *old_table;
mident *rtn_name;
size_t size, src_len;
- boolean_t found;
+ boolean_t found, duplicated;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -82,20 +91,11 @@ bool zlput_rname (rhdtyp *hdr)
} else
{ /* Entry exists. Update it */
old_rhead = (rhdtyp *)mid->rt_adr;
- /* Verify routine is not currently active. If it is, we cannot replace it -- wrong */
- USHBIN_ONLY(prev_active = old_rhead->active_rhead_adr);
- if (!handle_active_old_versions(old_rhead, hdr))
+ /* Verify routine is not currently active. If it is, we must duplicate it and keep it around */
+ if (!handle_active_old_versions(&duplicated, old_rhead, hdr))
return FALSE;
- USHBIN_ONLY( if (prev_active == old_rhead->active_rhead_adr))
- { /* old version not in use. free it */
- zr_remove(old_rhead, NOBREAKMSG); /* remove breakpoints (now inactive) */
- /* If source has been read in for old routine, free space. On VMS, source is associated with a routine name
- * table entry. On UNIX, source is associated with a routine header, and we may have different sources for
- * different linked versions of the same routine name.
- */
- free_src_tbl(old_rhead);
- zr_release(old_rhead); /* release private code section */
- }
+ if (!duplicated)
+ zr_unlink_rtn(old_rhead, FALSE); /* Release private code sections no longer in use */
# ifndef USHBIN_SUPPORTED
hdr->old_rhead_ptr = (int4)old_rhead;
# else /* USHBIN_SUPPORTED */
@@ -108,28 +108,47 @@ bool zlput_rname (rhdtyp *hdr)
return TRUE;
}
-STATICFNDEF boolean_t handle_active_old_versions(rhdtyp *old_rhead, rhdtyp *hdr)
+/* Routine to discover if a given routine name is on the M stack and, if TRUE, optionally identify whether the routine
+ * is the same (exact) routine we are running now (which some routines care about since it signals a need to clone the
+ * header so the original can be repurposed for a new flavor of the routine).
+ *
+ * Parameters:
+ * rtnhdr - The routine header to start our backwards search at.
+ * need_duplicate - Address of boolean_t to set if is the exact same routine (same routine header address).
+ */
+boolean_t on_stack(rhdtyp *rtnhdr, boolean_t *need_duplicate)
{
+ rhdtyp *rhdr;
stack_frame *fp;
- rhdtyp *rhead, *new_rhead;
- boolean_t need_duplicate, on_stack;
- ssize_t sect_rw_nonrel_size;
- DCL_THREADGBL_ACCESS;
- SETUP_THREADGBL_ACCESS;
- assert(old_rhead == CURRENT_RHEAD_ADR(old_rhead));
- on_stack = FALSE;
- need_duplicate = FALSE;
+ if (NULL != need_duplicate)
+ *need_duplicate = FALSE;
for (fp = frame_pointer; NULL != fp; fp = SKIP_BASE_FRAME(fp->old_frame_pointer))
{
- if (MSTR_EQ(&fp->rvector->routine_name, &old_rhead->routine_name))
+ if (MSTR_EQ(&fp->rvector->routine_name, &rtnhdr->routine_name))
{
- on_stack = TRUE;
- if (CURRENT_RHEAD_ADR(fp->rvector) == old_rhead)
- need_duplicate = TRUE;
+ if ((NULL != need_duplicate) && (CURRENT_RHEAD_ADR(fp->rvector) == rtnhdr))
+ *need_duplicate = TRUE;
+ return TRUE;
}
}
- if (on_stack)
+ return FALSE;
+}
+
+STATICFNDEF boolean_t handle_active_old_versions(boolean_t *duplicated, rhdtyp *old_rhead, rhdtyp *hdr)
+{
+ stack_frame *fp;
+ rhdtyp *rhead, *new_rhead;
+ boolean_t need_duplicate, is_on_stack;
+ ssize_t sect_rw_nonrel_size;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ assert(old_rhead == CURRENT_RHEAD_ADR(old_rhead));
+ is_on_stack = FALSE;
+ *duplicated = FALSE;
+ is_on_stack = on_stack(old_rhead, &need_duplicate);
+ if (is_on_stack)
{
# ifdef USHBIN_SUPPORTED
if (LINK_NORECURSIVE == TREF(relink_allowed))
@@ -142,56 +161,22 @@ STATICFNDEF boolean_t handle_active_old_versions(rhdtyp *old_rhead, rhdtyp *hdr)
new_rhead = (rhdtyp *)malloc(SIZEOF(rhdtyp));
*new_rhead = *old_rhead;
new_rhead->current_rhead_adr = new_rhead;
- old_rhead->active_rhead_adr = new_rhead; /* reserve previous version on active chain */
+ old_rhead->active_rhead_adr = new_rhead; /* Reserve previous version on active chain */
for (fp = frame_pointer; NULL != fp; fp = SKIP_BASE_FRAME(fp->old_frame_pointer))
if (CURRENT_RHEAD_ADR(fp->rvector) == old_rhead)
- fp->rvector = new_rhead; /* point frame's code vector at reserved copy of old routine version */
- /* any field (e.g. the label table) that is currently shared by old_rhead needs to be copied to a separate area
+ fp->rvector = new_rhead; /* Point frame's code vector at reserved copy of old routine version */
+ /* Any field (e.g. the label table) that is currently shared by old_rhead needs to be copied to a separate area
* other fields (e.g. literal mvals) will be redirected for old_rhead, so we just need to keep the older version
* around (don't free it).
*/
sect_rw_nonrel_size = old_rhead->labtab_len * SIZEOF(lab_tabent);
new_rhead->labtab_adr = (lab_tabent *)malloc(sect_rw_nonrel_size);
memcpy(new_rhead->labtab_adr, old_rhead->labtab_adr, sect_rw_nonrel_size);
- /* make sure to: skip urx_remove, do not free code section, etc. */
- /* ALSO: we need to go through resolve linkage table entries corresponding to this the old version, and re-resolve
+ /* Make sure to: skip urx_remove, do not free code section, etc. */
+ /* ALSO: We need to go through resolve linkage table entries corresponding to this the old version, and re-resolve
* them to point into the new version */
+ *duplicated = TRUE;
}
# endif /* USHBIN_SUPPORTED */
return TRUE;
}
-
-#ifdef USHBIN_SUPPORTED
-void zr_release(rhdtyp *old_rhead)
-{
- if (!old_rhead->shlib_handle)
- { /* Migrate text literals pointing into text area we are about to throw away into the stringpool.
- We also can release the read-only releasable segment as it is no longer needed.
- */
- stp_move((char *)old_rhead->literal_text_adr,
- (char *)(old_rhead->literal_text_adr + old_rhead->literal_text_len));
- zlmov_lnames(old_rhead); /* copy the label names from literal pool to malloc'd area */
- GTM_TEXT_FREE(old_rhead->ptext_adr);
- /* Reset the routine header pointers to the sections we just freed up.
- * NOTE: literal_text_adr shouldn't be reset as it points to the label area malloc'd
- * in zlmov_lnames() */
- old_rhead->ptext_adr = old_rhead->ptext_end_adr = NULL;
- old_rhead->lnrtab_adr = NULL;
- }
- urx_remove(old_rhead);
- free(RW_REL_START_ADR(old_rhead)); /* Release the read-write releasable segments */
- old_rhead->literal_adr = NULL;
- old_rhead->vartab_adr = NULL;
- free(old_rhead->linkage_adr); /* Release the old linkage section */
- old_rhead->linkage_adr = NULL;
-}
-#else /* non-USHBIN_SUPPORTED platforms */
-void zr_release(rhdtyp *old_rhead)
-{
- if (!old_rhead->old_rhead_ptr)
- {
- fix_pages((unsigned char *)old_rhead, (unsigned char *)LNRTAB_ADR(old_rhead)
- + (SIZEOF(lnr_tabent) * old_rhead->lnrtab_len));
- }
-}
-#endif
diff --git a/sr_port/zr_put_free.c b/sr_port/zr_put_free.c
index ee2ef02..75524f0 100644
--- a/sr_port/zr_put_free.c
+++ b/sr_port/zr_put_free.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -38,13 +38,13 @@ void zr_put_free(z_records *zrecs, zbrk_struct *z_ptr)
z_ptr->action = NULL;
}
/* In the generated code, change the offset in TRANSFER TABLE */
-#ifdef COMPLEX_INSTRUCTION_UPDATE
+# ifdef COMPLEX_INSTRUCTION_UPDATE
EXTRACT_AND_UPDATE_INST(z_ptr->mpc, z_ptr->m_opcode);
-#else
+# else
*z_ptr->mpc = z_ptr->m_opcode;
-#endif
+# endif
inst_flush(z_ptr->mpc, SIZEOF(INST_TYPE));
-#ifdef USHBIN_SUPPORTED
+# ifdef USHBIN_SUPPORTED
if (((z_ptr == zrecs->beg) || !MIDENT_EQ((z_ptr - 1)->rtn, z_ptr->rtn)) &&
(((z_ptr + 1) == zrecs->free) || !MIDENT_EQ((z_ptr + 1)->rtn, z_ptr->rtn)))
{ /* No more breakpoints in the routine we just removed a break from. Note that since zrecs is sorted based
@@ -56,10 +56,10 @@ void zr_put_free(z_records *zrecs, zbrk_struct *z_ptr)
rtn_str.len = z_ptr->rtn->len;
rtn_str.addr = z_ptr->rtn->addr;
routine = find_rtn_hdr(&rtn_str);
- if (NULL != routine->shlib_handle) /* don't need the private copy any more, revert back to shared copy */
+ if (NULL != routine->shared_ptext_adr) /* don't need the private copy any more, revert back to shared copy */
release_private_code_copy(routine);
}
-#endif
+# endif
zrecs->free--;
/* potentially overlapped memory, use memmove, not memcpy */
memmove((char *)z_ptr, (char *)(z_ptr + 1), (zrecs->free - z_ptr) * SIZEOF(zbrk_struct));
diff --git a/sr_port/zr_remove.c b/sr_port/zr_remove_zbrks.c
similarity index 80%
rename from sr_port/zr_remove.c
rename to sr_port/zr_remove_zbrks.c
index 5278e73..f8a2dee 100644
--- a/sr_port/zr_remove.c
+++ b/sr_port/zr_remove_zbrks.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2002, 2011 Fidelity Information Services, Inc *
+ * Copyright 2002, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,8 +21,8 @@ GBLREF int4 break_message_mask;
GTMTRIG_ONLY(error_def(ERR_TRIGZBREAKREM);)
-/* remove all breaks in rtn */
-void zr_remove(rhdtyp *rtn, boolean_t notify_is_trigger)
+/* Remove all ZBREAKs in given rtn */
+void zr_remove_zbrks(rhdtyp *rtn, boolean_t notify_is_trigger)
{
zbrk_struct *zb_ptr;
GTMTRIG_ONLY(boolean_t msg_done = FALSE;)
@@ -34,7 +34,8 @@ void zr_remove(rhdtyp *rtn, boolean_t notify_is_trigger)
# ifdef GTM_TRIGGER
if ((BREAKMSG == notify_is_trigger) && !msg_done && (break_message_mask & TRIGGER_ZBREAK_REMOVED_MASK))
{ /* Message is info level */
- gtm_putmsg(VARLSTCNT(4) ERR_TRIGZBREAKREM, 2, rtn->routine_name.len, rtn->routine_name.addr);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TRIGZBREAKREM, 2, rtn->routine_name.len,
+ rtn->routine_name.addr);
msg_done = TRUE;
}
# endif
diff --git a/sr_port/zr_unlink_rtn.c b/sr_port/zr_unlink_rtn.c
new file mode 100644
index 0000000..3005298
--- /dev/null
+++ b/sr_port/zr_unlink_rtn.c
@@ -0,0 +1,150 @@
+/****************************************************************
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include <stddef.h> /* for offsetof macro */
+#include "gtm_stdlib.h"
+#include "gtm_string.h"
+#include "sys/mman.h"
+
+#include <rtnhdr.h>
+#include "fix_pages.h"
+#include "zbreak.h"
+#include "private_code_copy.h"
+#include "cmd_qlf.h"
+#include "urx.h"
+#include "stringpool.h"
+#include "gtm_text_alloc.h"
+#include "zr_unlink_rtn.h"
+#include "zroutines.h"
+#include "incr_link.h"
+
+/* Routine to unlink given old flavor of routine (as much of it as we are able).
+ *
+ * Parameters:
+ *
+ * old_rhead - Old routine header to be processed
+ * free_all - Currently only true by gtm_unlink_all. If TRUE, releases routine in its entirety - nothing stays behind.
+ * If FALSE, only the "releasable" sections as noted in comments of obj_code.c are released.
+ *
+ * Note when a "normal" routine is re-linked, not all of it is removed. Both the original routine header and the label
+ * table are retained since addresses to those things exist in the linkage tables of other routines. But in the case of
+ * triggers or "unlink-all" (ZGOTO 0:entryref), the entire routine is removed.
+ */
+void zr_unlink_rtn(rhdtyp *old_rhead, boolean_t free_all)
+{
+ unsigned char *map_adr; /* If code section is mmapped from shared .o file */
+ textElem *telem;
+ rhdtyp *rhdr, *next_rhdr;
+
+ zr_remove_zbrks(old_rhead, NOBREAKMSG); /* Remove breakpoints (now inactive) */
+ /* If source has been read in for old routine, free space. On VMS, source is associated with a routine name
+ * table entry. On UNIX, source is associated with a routine header, and we may have different sources for
+ * different linked versions of the same routine name.
+ */
+ free_src_tbl(old_rhead);
+# ifdef USHBIN_SUPPORTED
+ urx_remove(old_rhead); /* Remove all unresolved entries for this routine */
+ /* We are about to release program areas containing literal text that could be pointed to by
+ * local variable mvals that are being kept so migrate program literals to the stringpool.
+ * Migrate text literals pointing into text area we are about to throw away into the stringpool.
+ * We also can release the read-only releasable segment as it is no longer needed.
+ * NOTE: go ahead and move these even if old routine is in a shared library and we aren't closing
+ * the shared library. Anything we move but isn't actually needed will be weeded out in the next
+ * stringpool garbage collection.
+ */
+ if (0 < old_rhead->literal_text_len)
+ stp_move((char *)old_rhead->literal_text_adr,
+ (char *)(old_rhead->literal_text_adr + old_rhead->literal_text_len));
+ if (NULL == old_rhead->shlib_handle)
+ { /* Object is not resident in a shared library */
+ if (!free_all)
+ zlmov_lnames(old_rhead); /* Copy the label names from literal pool to malloc'd area */
+ if (0 < old_rhead->shared_len)
+ { /* Object is being shared via mmap() */
+ assert(NULL != old_rhead->shared_ptext_adr);
+ assert(old_rhead->shared_ptext_adr == old_rhead->ptext_adr);
+ map_adr = old_rhead->shared_ptext_adr - SIZEOF(rhdtyp)- NATIVE_HDR_LEN;
+ munmap(map_adr, old_rhead->shared_len);
+
+ } else
+ { /* Process private linked object */
+ GTM_TEXT_FREE(old_rhead->ptext_adr);
+ }
+ /* Reset the routine header pointers to the sections we just freed up.
+ * NOTE: literal_text_adr shouldn't be reset as it points to the label area malloc'd
+ * in zlmov_lnames().
+ */
+ old_rhead->ptext_adr = old_rhead->ptext_end_adr = NULL;
+ old_rhead->lnrtab_adr = NULL;
+ }
+ free(RW_REL_START_ADR(old_rhead)); /* Release the read-write releasable segments */
+ old_rhead->literal_adr = NULL;
+ old_rhead->vartab_adr = NULL;
+ free(old_rhead->linkage_adr); /* Release the old linkage section */
+ old_rhead->linkage_adr = NULL;
+# else
+ if (!old_rhead->old_rhead_ptr)
+ { /* On VMS, this makes the routine "malleable" and on UNIX tiz a stub */
+ fix_pages((unsigned char *)old_rhead, (unsigned char *)LNRTAB_ADR(old_rhead)
+ + (SIZEOF(lnr_tabent) * old_rhead->lnrtab_len));
+ }
+# endif
+ if (free_all)
+ { /* We are not keeping any parts of this routine (generally used for triggers and for gtm_unlink_all()) */
+# ifdef USHBIN_SUPPORTED
+ free(old_rhead->labtab_adr); /* Usually non-releasable but not in this case */
+ if (old_rhead->lbltext_ptr)
+ free(old_rhead->lbltext_ptr); /* Get rid of any label text hangers-on */
+ if (old_rhead->shared_len) /* If this is a shared object (not library), drop rtn name/path text */
+ free(old_rhead->src_full_name.addr);
+ /* Run the chain of old (replaced) versions freeing them also if they exist*/
+ for (rhdr = OLD_RHEAD_ADR(old_rhead); NULL != rhdr; rhdr = next_rhdr)
+ {
+ next_rhdr = rhdr->old_rhead_adr;
+ if (rhdr->lbltext_ptr)
+ free(rhdr->lbltext_ptr); /* Get rid of any label text hangers-on */
+ if (rhdr->shared_len) /* If this is a shared object, drop rtn name/path text */
+ free(rhdr->src_full_name.addr);
+ free(rhdr->labtab_adr); /* Free dangling label table */
+ free(rhdr);
+ }
+ free(old_rhead);
+# elif !defined(VMS)
+# if (!defined(__linux__) && !defined(__CYGWIN__)) || !defined(__i386) || !defined(COMP_GTA)
+# error Unsupported NON-USHBIN platform
+# endif
+ /* For a non-shared binary platform we need to get an approximate addr range for stp_move. This is not
+ * done when a routine is replaced on these platforms but in this case we need to since the routines are
+ * going away which will cause problems with any local variables or environment varspointing to these
+ * literals.
+ *
+ * In this format, the only platform we support currently is Linux-x86 (i386) which uses GTM_TEXT_ALLOC()
+ * to allocate special storage for it to put executable code in. We can access the storage header for
+ * this storage and find out how big it is and use that information to give stp_move a good range since
+ * the literal segment occurs right at the end of allocated storage (for which there is no pointer
+ * in the fileheader). (Note we allow CYGWIN in here too but it has not been tested at this time)
+ */
+ telem = (textElem *)((char *)old_rhead - offsetof(textElem, userStorage));
+ assert(TextAllocated == telem->state);
+ stp_move((char *)LNRTAB_ADR(old_rhead) + (old_rhead->lnrtab_len * SIZEOF(lnr_tabent)),
+ (char *)old_rhead + telem->realLen);
+ /* Run the chain of old (replaced) versions freeing them first */
+ for (rhdr = OLD_RHEAD_ADR(old_rhead); old_rhead != rhdr; rhdr = next_rhdr)
+ {
+ next_rhdr = (rhdtyp *)rhdr->old_rhead_ptr;
+ GTM_TEXT_FREE(rhdr);
+ }
+ GTM_TEXT_FREE(old_rhead);
+# endif
+ }
+}
diff --git a/sr_port/term_setup.h b/sr_port/zr_unlink_rtn.h
similarity index 64%
copy from sr_port/term_setup.h
copy to sr_port/zr_unlink_rtn.h
index d4549b3..1783424 100644
--- a/sr_port/term_setup.h
+++ b/sr_port/zr_unlink_rtn.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,9 +9,9 @@
* *
****************************************************************/
-#ifndef TERM_SETUP_INCLUDED
-#define TERM_SETUP_INCLUDED
+#ifndef GTM_UNLINK_H_INCLUDED
+#define GTM_UNLINK_H_INCLUDED
-void term_setup(bool ctrlc_enable);
+void zr_unlink_rtn(rhdtyp *old_rhead, boolean_t free_all);
-#endif /* TERM_SETUP_INCLUDED */
+#endif /* GTM_UNLINK_H_INCLUDED */
diff --git a/sr_port/zro_init.c b/sr_port/zro_init.c
index 3edc183..eb82b01 100644
--- a/sr_port/zro_init.c
+++ b/sr_port/zro_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,9 +21,9 @@
error_def(ERR_LOGTOOLONG);
-#define MAX_NUMBER_FILENAMES 256*MAX_TRANS_NAME_LEN
+#define MAX_NUMBER_FILENAMES (256 * MAX_TRANS_NAME_LEN)
-void zro_init (void)
+void zro_init(void)
{
int4 status;
mstr val, tn;
@@ -40,10 +40,10 @@ void zro_init (void)
{
# ifdef UNIX
if (SS_LOG2LONG == status)
- rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.len, val.addr, SIZEOF(buf1) - 1);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.len, val.addr, SIZEOF(buf1) - 1);
else
# endif
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
if (status == SS_NOLOGNAM)
(TREF(dollar_zroutines)).len = 0;
diff --git a/sr_port/zshow_params.h b/sr_port/zshow_params.h
index d7ef7f7..d0c4355 100644
--- a/sr_port/zshow_params.h
+++ b/sr_port/zshow_params.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -66,6 +66,7 @@ zshow_rec,
zshow_shar,
zshow_shell,
zshow_stderr,
+zshow_stream,
zshow_term,
zshow_ttsy,
zshow_type,
diff --git a/sr_port/gtm_imagetype_init.h b/sr_port/zsocket.h
similarity index 55%
rename from sr_port/gtm_imagetype_init.h
rename to sr_port/zsocket.h
index a46766a..80464cc 100644
--- a/sr_port/gtm_imagetype_init.h
+++ b/sr_port/zsocket.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010 Fidelity Information Services, Inc *
+ * Copyright 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -8,10 +8,16 @@
* the license, please stop and do not read further. *
* *
****************************************************************/
-
-#ifndef GTM_IMAGETYPE_INIT_INCLUDED
-#define GTM_IMAGETYPE_INIT_INCLUDED
-
-void gtm_imagetype_init(enum gtmImageTypes img_type);
-
+#ifndef ZSOCKET_H
+#define ZSOCKET_H
+enum zsocket_levels {
+ level_device, /* io_desc_struct */
+ level_socdev, /* d_socket_struct */
+ level_socket /* socket_struct */
+};
+#define ZSOCKETITEM(A,B,C,D) B
+enum zsocket_code {
+#include "zsockettab.h"
+};
+#undef ZSOCKETITEM
#endif
diff --git a/sr_port/zsockettab.h b/sr_port/zsockettab.h
new file mode 100644
index 0000000..61d8067
--- /dev/null
+++ b/sr_port/zsockettab.h
@@ -0,0 +1,31 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+/* Any changes here must be reflected in op_fnzsocket.c especially zsocket_indextab */
+ZSOCKETITEM("CURRENTINDEX", zsocket_currindex, MV_NM, level_socdev),
+ZSOCKETITEM("DELIMITER", zsocket_delimiter, MV_STR|MV_NM, level_socket),
+ZSOCKETITEM("DESCRIPTOR", zsocket_descriptor, MV_NM, level_socket),
+ZSOCKETITEM("HOWCREATED", zsocket_howcreated, MV_STR, level_socket),
+ZSOCKETITEM("INDEX", zsocket_index, MV_NM, level_socket),
+ZSOCKETITEM("IOERROR", zsocket_ioerror, MV_STR, level_socket),
+ZSOCKETITEM("LOCALADDRESS", zsocket_localaddress, MV_STR, level_socket),
+ZSOCKETITEM("LOCALPORT", zsocket_localport, MV_NM, level_socket),
+ZSOCKETITEM("MOREREADTIME", zsocket_morereadtime, MV_NM, level_socket),
+ZSOCKETITEM("NUMBER", zsocket_number, MV_NM, level_socdev),
+ZSOCKETITEM("PARENT", zsocket_parent, MV_STR, level_socket),
+ZSOCKETITEM("PROTOCOL", zsocket_protocol, MV_STR, level_socket),
+ZSOCKETITEM("REMOTEADDRESS", zsocket_remoteaddress, MV_STR, level_socket),
+ZSOCKETITEM("REMOTEPORT", zsocket_remoteport, MV_NM, level_socket),
+ZSOCKETITEM("SOCKETHANDLE", zsocket_sockethandle, MV_STR, level_socket),
+ZSOCKETITEM("STATE", zsocket_state, MV_STR, level_socket),
+ZSOCKETITEM("ZBFSIZE", zsocket_zbfsize, MV_NM, level_socket),
+ZSOCKETITEM("ZDELAY", zsocket_zdelay, MV_STR, level_socket),
+ZSOCKETITEM("ZFF", zsocket_zff, MV_STR, level_socket),
+ZSOCKETITEM("ZIBFSIZE", zsocket_zibfsize, MV_NM, level_socket)
diff --git a/sr_unix/CMakeLists.txt b/sr_unix/CMakeLists.txt
index cca42e8..40f5eb4 100644
--- a/sr_unix/CMakeLists.txt
+++ b/sr_unix/CMakeLists.txt
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2012, 2013 Fidelity Information Services, Inc #
+# Copyright 2012, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -36,8 +36,11 @@ if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
-# If it's a debug build make sure GT.M uses all of its debug options
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
+# Enable GT.M debug options unless directed not to enable them. Added to build without whitebox tests.
+set(GTM_ENABLE_DEBUG 1 CACHE BOOL "Enable GT.M debug options")
+if(GTM_ENABLE_DEBUG)
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
+endif()
set(install_permissions_script
OWNER_READ OWNER_EXECUTE OWNER_WRITE
@@ -57,9 +60,8 @@ set(gtm_osarch_libs "")
set(gt_src_list)
set(sources_used "")
set(extralibs "")
-# Disable encryption for the time being. Need to change this to invoke the gtmcrypt Makefile AS 2013.12.18
-set(is_encryption_supported 0)
-set(libmumpsrestoreregex "")
+set(GTMCRYPTLIB "GCRYPT")
+set(GTMCRYPTALGO "AES256CFB")
message("--> OS = ${CMAKE_SYSTEM_NAME} / ARCH = ${CMAKE_SYSTEM_PROCESSOR}")
# Establish platform
# Except for Solaris, CMAKE_COMPILER_IS_GNUCC is true
@@ -74,6 +76,7 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
else()
message(FATAL_ERROR "--> OS = ${CMAKE_SYSTEM_NAME} / ARCH = ${CMAKE_SYSTEM_PROCESSOR}")
endif()
+message("--> Encryption Library = ${GTMCRYPTLIB} / Algorithm = ${GTMCRYPTALGO}")
# Choose where to get bootstrap sources.
set(GTM_DIST "" CACHE PATH "Existing GT.M Distribution")
@@ -169,11 +172,6 @@ macro(set_source_list target)
set(src ${d}/${fname})
set("source_used_${fname}" 1)
list(APPEND sources_used ${source_dir_${d}}/${fname})
- if(NOT "${libmumpsrestoreregex}" STREQUAL "")
- if(";${name};" MATCHES ";(${libmumpsrestoreregex});")
- set("source_used_${fname}" 0)
- endif()
- endif()
break()
endif()
endforeach()
@@ -204,9 +202,6 @@ load_source_list(libgtcm sr_unix_cm/libgtcm.list)
load_source_list(liblke sr_unix/liblke.list)
load_source_list(libmupip sr_unix/libmupip.list)
load_source_list(libstub sr_unix/libstub.list)
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
- load_source_list(libgtmrpc sr_sun/libgtmrpc.list)
-endif()
# Assign sources to executables.
set_source_list(gtm_threadgbl_deftypes gtm_threadgbl_deftypes)
@@ -221,18 +216,14 @@ set_source_list(gtcm_server gtcm_main omi_srvc_xct)
set_source_list(gtcm_shmclean gtcm_shmclean)
set_source_list(gtmsecshr gtmsecshr_wrapper)
set_source_list(gtmsecshr_real gtmsecshr)
-set_source_list(libgtmcrypt gtmcrypt_ref gtmcrypt_pk_ref gtmcrypt_dbk_ref gtmcrypt_sym_ref)
-set_source_list(libgtmtls gtm_tls_impl)
-set_source_list(libgtmcryptutil gtmcrypt_util)
+set_source_list(libgtmcrypt gtmcrypt_ref gtmcrypt_pk_ref gtmcrypt_dbk_ref gtmcrypt_sym_ref gtmcrypt_util)
+set_source_list(libgtmtls gtm_tls_impl gtmcrypt_util)
set_source_list(libgtmshr gtm_main)
set_source_list(lke lke lke_cmd)
set_source_list(maskpass maskpass gtmcrypt_util)
set_source_list(mumps gtm)
set_source_list(mupip mupip mupip_cmd)
set_source_list(semstat2 semstat2)
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
- set_source_list(gtm_svc gtm_svc gtm_rpc_init gtm_dal_svc)
-endif()
#-----------------------------------------------------------------------------
# libmumps gets leftover sources, so compute the remaining list.
@@ -386,7 +377,7 @@ foreach(lib
endforeach()
# TODO: find_package or find_library for system libs?
-include_directories ("/usr/local/include")
+include_directories (/usr/local/include)
target_link_libraries(libmumps ${libmumpslibs})
add_executable(mumps ${mumps_SOURCES})
@@ -444,18 +435,6 @@ add_executable(semstat2 ${semstat2_SOURCES})
add_executable(ftok ${ftok_SOURCES})
target_link_libraries(ftok libmumps libstub)
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
- add_executable(gtm_svc ${gtm_svc_SOURCES})
- target_link_libraries(gtm_svc libmumps libgnpclient libcmisockettcp libgtmrpc)
-endif()
-foreach(t ${with_export})
- set_target_properties(${t} PROPERTIES
- LINK_FLAGS "${gtm_link}"
- LINK_DEPENDS "${gtm_dep}"
- )
- add_dependencies(${t} gen_export)
-endforeach()
-
add_library(libgtmshr MODULE ${libgtmshr_SOURCES})
set_property(TARGET libgtmshr PROPERTY OUTPUT_NAME gtmshr)
target_link_libraries(libgtmshr libmumps libgnpclient libcmisockettcp)
@@ -466,62 +445,51 @@ set_target_properties(libgtmshr PROPERTIES
add_dependencies(libgtmshr gen_export)
add_dependencies(mumps libgtmshr)
-if(is_encryption_supported)
- # Iterate over the list of GPG related libraries
- foreach(gpglib gpg-error gpgme gcrypt)
- # For each library, we need a new CMake variable, hence GPGLIB_${gpglib}
- find_library(GPGLIB_${gpglib} NAME ${gpglib} PATHS ${CMAKE_LIBRARY_PATH})
- # Append the found library to the list
- set(GPG_LIBRARIES ${GPG_LIBRARIES} ${GPGLIB_${gpglib}})
- endforeach()
-
- # Iterate over the list of SSL related libraries
- foreach(ssl)
- # For each library, we need a new CMake variable, hence TLSLIB_${tlslib}
- find_library(TLSLIB_${tlslib} NAME ${tlslib} PATHS ${CMAKE_LIBRARY_PATH})
- # Append the found library to the list
- set(TLS_LIBRARIES ${TLS_LIBRARIES} ${TLSLIB_${tlslib}})
- endforeach()
+# Iterate over the list of GPG related libraries
+foreach(gpglib gpg-error gpgme gcrypt config)
+ # For each library, we need a new CMake variable, hence GPGLIB_${gpglib}
+ find_library(GPGLIB_${gpglib} NAME ${gpglib} PATHS ${CMAKE_LIBRARY_PATH})
+ # Append the found library to the list
+ set(GPG_LIBRARIES ${GPG_LIBRARIES} ${GPGLIB_${gpglib}})
+endforeach()
- add_library(libgtmcrypt MODULE ${libgtmcrypt_SOURCES})
- set_target_properties(libgtmcrypt PROPERTIES
- OUTPUT_NAME gtmcrypt
- COMPILE_DEFINITIONS "USE_GCRYPT -DUSE_AES256CFB"
- LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
- )
- target_link_libraries(libgtmcrypt ${GPG_LIBRARIES})
- install(TARGETS libgtmcrypt DESTINATION ${GTM_INSTALL_DIR}/plugin)
+# Iterate over the list of SSL related libraries
+foreach(tlslib ssl crypto config)
+ # For each library, we need a new CMake variable, hence TLSLIB_${tlslib}
+ find_library(TLSLIB_${tlslib} NAME ${tlslib} PATHS ${CMAKE_LIBRARY_PATH})
+ # Append the found library to the list
+ set(TLS_LIBRARIES ${TLS_LIBRARIES} ${TLSLIB_${tlslib}})
+endforeach()
- add_library(libgtmtls MODULE ${libgtmtls_SOURCES})
- set_target_properties(libgtmtls PROPERTIES
- OUTPUT_NAME gtmtls
- LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
- )
- target_link_libraries(libgtmtls ${TLS_LIBRARIES})
- install(TARGETS libgtmtls DESTINATION ${GTM_INSTALL_DIR}/plugin)
-
- add_library(libgtmcryptutil MODULE ${libgtmcryptutil_SOURCES})
- set_target_properties(libgtmcryptutil PROPERTIES
- OUTPUT_NAME gtmcryptutil
- COMPILE_DEFINITIONS "USE_GCRYPT -DUSE_AES256CFB"
- LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
- )
- target_link_libraries(libgtmcryptutil ${GPG_LIBRARIES})
- install(TARGETS libgtmcryptutil DESTINATION ${GTM_INSTALL_DIR}/plugin)
-
- add_executable(maskpass ${maskpass_SOURCES})
- target_link_libraries(maskpass ${GPG_LIBRARIES})
- set_target_properties(maskpass PROPERTIES
- COMPILE_DEFINITIONS "USE_GCRYPT -DUSE_SYSLIB_FUNCS"
- RUNTIME_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin/gtmcrypt
- )
- install(TARGETS maskpass DESTINATION ${GTM_INSTALL_DIR}/plugin/gtmcrypt)
-endif()
+add_library(libgtmcrypt MODULE ${libgtmcrypt_SOURCES})
+set_target_properties(libgtmcrypt PROPERTIES
+ OUTPUT_NAME gtmcrypt
+ COMPILE_DEFINITIONS "USE_${GTMCRYPTLIB} -DUSE_${GTMCRYPTALGO}"
+ LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
+ )
+target_link_libraries(libgtmcrypt ${GPG_LIBRARIES})
+install(TARGETS libgtmcrypt DESTINATION ${GTM_INSTALL_DIR}/plugin)
+
+add_library(libgtmtls MODULE ${libgtmtls_SOURCES})
+set_target_properties(libgtmtls PROPERTIES
+ OUTPUT_NAME gtmtls
+ COMPILE_DEFINITIONS "USE_OPENSSL"
+ LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
+ )
+target_link_libraries(libgtmtls ${TLS_LIBRARIES})
+install(TARGETS libgtmtls DESTINATION ${GTM_INSTALL_DIR}/plugin)
+
+add_executable(maskpass ${maskpass_SOURCES})
+target_link_libraries(maskpass ${GPG_LIBRARIES} ${TLS_LIBRARIES})
+set_target_properties(maskpass PROPERTIES
+ COMPILE_DEFINITIONS "USE_${GTMCRYPTLIB} -DUSE_SYSLIB_FUNCS"
+ RUNTIME_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin/gtmcrypt
+ )
+install(TARGETS maskpass DESTINATION ${GTM_INSTALL_DIR}/plugin/gtmcrypt)
# Always copy files into the plugin directory
foreach(f
Makefile.mk
- add_db_key.sh
encrypt_sign_db_key.sh
gen_keypair.sh
gen_sym_hash.sh
diff --git a/sr_unix/Makefile.mk b/sr_unix/Makefile.mk
index 959b991..7e3789c 100644
--- a/sr_unix/Makefile.mk
+++ b/sr_unix/Makefile.mk
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2013 Fidelity Information Services, Inc #
+# Copyright 2013, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -133,9 +133,11 @@ endif
# Common header and library paths
IFLAGS += -I /usr/local/ssl/include -I /usr/local/include -I /usr/include -I $(gtm_dist) -I $(CURDIR)
ifeq ($(BIT64),0)
- LIBFLAGS += -L /usr/local/ssl/lib -L /usr/local/lib64 -L /usr/local/lib -L /usr/lib64 -L /usr/lib -L /lib64 -L /lib -L `pwd`
+ LIBFLAGS += -L /usr/local/ssl/lib -L /usr/lib/x86_64-linux-gnu -L /usr/local/lib64
+ LIBFLAGS += -L /usr/local/lib -L /usr/lib64 -L /usr/lib -L /lib64 -L /lib -L `pwd`
else
- LIBFLAGS += -L /usr/local/ssl/lib -L /usr/local/lib32 -L /usr/local/lib -L /usr/lib32 -L /usr/lib -L /lib32 -L /lib -L `pwd`
+ LIBFLAGS += -L /usr/local/ssl/lib -L /usr/lib/x86-linux-gnu -L /usr/local/lib32
+ LIBFLAGS += -L /usr/local/lib -L /usr/lib32 -L /usr/lib -L /lib32 -L /lib -L `pwd`
endif
CFLAGS += $(IFLAGS)
diff --git a/sr_unix/add_db_key.sh b/sr_unix/add_db_key.sh
deleted file mode 100644
index bdcfdd0..0000000
--- a/sr_unix/add_db_key.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#################################################################
-# #
-# Copyright 2010, 2011 Fidelity Information Services, Inc #
-# #
-# This source code contains the intellectual property #
-# of its copyright holder(s), and is made available #
-# under a license. If you do not know the terms of #
-# the license, please stop and do not read further. #
-# #
-#################################################################
-
-#############################################################################################
-#
-# add_db_key.sh - Adds a new entry into the db key file. All paths provided in the
-# command line are converted to absolute paths and stored in the db key file.
-#
-# Arguments:
-# $1 - relative/absolute path of the database file (does not need to exist)
-# $2 - relative/absolute path of the encrypted key file for this database($1)
-# (must exist)
-# $3 - (optional) if provided, denotes the output file (db key file).
-# If not supplied, the value is taken from $gtm_dbkeys.
-# If $gtm_dbkeys doesn't exist, looks for $HOME/.gtm_dbkeys, which is
-# created if it does not exist.
-#
-#############################################################################################
-
-# echo and options
-ECHO=/bin/echo
-ECHO_OPTIONS=""
-#Linux honors escape sequence only when run with -e
-if [ "Linux" = "`uname -s`" ] ; then ECHO_OPTIONS="-e" ; fi
-
-# Database filename and key file name are required; master can default
-if [ $# -lt 2 ]; then $ECHO "Usage: `basename $0` database_file key_file [master_key_file]" ; exit 1 ; fi
-
-case $2 in
- /*) keyfile=$2 ;;
- *) keyfile=$PWD/$2 ;;
-esac
-if [ ! -r "$keyfile" ] ; then $ECHO "Key file $keyfile does not exist or is not readable" ; exit 1 ; fi
-
-case $1 in
- /*) dbfile=$1 ;;
- *) dbfile=$PWD/$1 ;;
-esac
-
-if [ $# -ge 3 ] ; then master=$3
-elif [ -n "$gtm_dbkeys" ] ; then master=$gtm_dbkeys
-else master=$HOME/.gtm_dbkeys
-fi
-
-if [ -d $master -o -f $master ] ; then
- if [ -w $master ] ; then
- if [ -d $master ] ; then master=$master/.gtm_dbkeys ; fi
- else
- $ECHO "$master is not writable" ; exit 1
- fi
-else #Master does not exist; confirm that directory is writable
- tmp=`dirname $master` ; if [ -z "$tmp" ] ; then tmp=$PWD ; fi
- if [ ! -w $tmp ] ; then $ECHO "Directory $tmp not writable for master key file $master" ; exit 1 ; fi
-fi
-
-$ECHO dat $dbfile >>$master
-$ECHO key $keyfile >>$master
diff --git a/sr_unix/auto_zlink.c b/sr_unix/auto_zlink.c
index 7c2fe6a..9214738 100644
--- a/sr_unix/auto_zlink.c
+++ b/sr_unix/auto_zlink.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2003, 2010 Fidelity Information Services, Inc *
+ * Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -26,12 +26,16 @@ IA64_ONLY(GBLREF uint8 imm14;)
IA64_ONLY(GBLREF char asm_mode;)
/* Due to the complex instruction set of x86_64, we require a function to implement the macro VALID_CALLING_SEQUENCE
- and this function will calculate both the offsets (rtnhdr & labaddr) and store them into these global variables */
+ * and this function will calculate both the offsets (rtnhdr & labaddr) and store them into these global variables.
+ */
#if defined(__x86_64__) || defined(__MVS__) || defined(Linux390)
GBLDEF int4 rtnhdr_off;
GBLDEF int4 labaddr_off;
#endif
+error_def (ERR_LABELUNKNOWN);
+error_def (ERR_ROUTINEUNKNOWN);
+
rhdtyp *auto_zlink(mach_inst *pc, lnr_tabent ***line)
{
lnk_tabent *A_rtnhdr;
@@ -42,9 +46,13 @@ rhdtyp *auto_zlink(mach_inst *pc, lnr_tabent ***line)
rhdtyp *rhead;
urx_rtnref *rtnurx;
- error_def (ERR_LABELUNKNOWN);
- error_def (ERR_ROUTINEUNKNOWN);
-
+# ifdef USHBIN_SUPPORTED
+ /* With the current autorelink multi-opcode call (OP_RHD_EXT and OP_LAB_EXT prior to actual call), auto_zlink()
+ * isn't really at all used but this is likely to change in the next release which streamlines some of this so
+ * for now, this routine is not being nixed.
+ */
+ USHBIN_ONLY(assertpro(FALSE));
+# else
/* (ASSUMPTION)
* The instructions immediately preceding the current mpc form a transfer table call.
* There will be two arguments to this call:
@@ -60,10 +68,7 @@ rhdtyp *auto_zlink(mach_inst *pc, lnr_tabent ***line)
* registers are loaded via "load" instructions. However, this routine should never be invoked from direct
* mode because the applicable routine should have been ZLINK'ed by prior calls to op_labaddr and op_rhdaddr.
*/
-
- NON_IA64_ONLY(if (!VALID_CALLING_SEQUENCE(pc)))
- NON_IA64_ONLY(GTMASSERT;)
-
+ NON_IA64_ONLY(assertpro(VALID_CALLING_SEQUENCE(pc)));
/* Calling sequence O.K.; get address(address(routine header)) and address(address(label offset)). */
# ifdef __ia64 /* __ia64 */
{
@@ -80,21 +85,17 @@ rhdtyp *auto_zlink(mach_inst *pc, lnr_tabent ***line)
A_labaddr = (lnk_tabent *)(imm + frame_pointer->ctxt);
}
# endif /* __ia64 */
-
NON_IA64_ONLY(A_rtnhdr = (lnk_tabent *)(RTNHDR_PV_OFF(pc) + frame_pointer->ctxt);)
NON_IA64_ONLY(A_labaddr = (lnk_tabent *)(LABADDR_PV_OFF(pc) + frame_pointer->ctxt);)
-
if (azl_geturxrtn((char *)A_rtnhdr, &rname, &rtnurx))
{
assert(rname.len <= MAX_MIDENT_LEN);
assert(0 != rname.addr);
-
/* Copy rname into local storage because azl_geturxrtn sets rname.addr to an address that is
* free'd during op_zlink and before the call to find_rtn_hdr.
*/
memcpy(rname_buff.c, rname.addr, rname.len);
rname.addr = rname_buff.c;
-
assert(0 != rtnurx);
assert(azl_geturxlab((char *)A_labaddr, rtnurx));
assert(0 == find_rtn_hdr(&rname));
@@ -106,10 +107,11 @@ rhdtyp *auto_zlink(mach_inst *pc, lnr_tabent ***line)
{ /* Pull the linkage table reference out and return it to caller */
*line = (lnr_tabent **)(A_labaddr->ext_ref);
if (0 == *line)
- rts_error(VARLSTCNT(1) ERR_LABELUNKNOWN);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_LABELUNKNOWN);
return rhead;
}
}
- rts_error(VARLSTCNT(1) ERR_ROUTINEUNKNOWN);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ROUTINEUNKNOWN);
+# endif /* ifdef USHBIN_SUPPORTED */
return NULL; /* Compiler happiness phase */
}
diff --git a/sr_unix/bin_load.c b/sr_unix/bin_load.c
index 5bb2c2b..ca1b9e4 100644
--- a/sr_unix/bin_load.c
+++ b/sr_unix/bin_load.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -49,6 +49,7 @@
#include "zshow.h"
#include "hashtab_mname.h"
#include "min_max.h"
+#include "mu_interactive.h"
GBLREF bool mupip_DB_full;
GBLREF bool mu_ctrly_occurred;
@@ -61,11 +62,12 @@ GBLREF gv_key *gv_currkey;
GBLREF gv_namehead *gv_target;
GBLREF int4 gv_keysize;
GBLREF sgmnt_addrs *cs_addrs;
+GBLREF int onerror;
#ifdef GTM_CRYPT
GBLREF io_pair io_curr_device;
#endif
-error_def(ERR_CORRUPT);
+error_def(ERR_CORRUPTNODE);
error_def(ERR_GVIS);
error_def(ERR_TEXT);
error_def(ERR_LDBINFMT);
@@ -77,11 +79,13 @@ error_def(ERR_COLLATIONUNDEF);
error_def(ERR_OLDBINEXTRACT);
error_def(ERR_LOADINVCHSET);
error_def(ERR_LDSPANGLOINCMP);
+error_def(ERR_RECLOAD);
#define BIN_PUT 0
#define BIN_BIND 1
#define ERR_COR 2
#define BIN_KILL 3
+#define BIN_PUT_GVSPAN 4
#ifdef GTM_CRYPT
# define EMPTY_GTMCRYPT_HASH16 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
@@ -133,8 +137,7 @@ error_def(ERR_LDSPANGLOINCMP);
if (file_offset != last_sn_error_offset) \
{ \
last_sn_error_offset = file_offset; \
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_LDSPANGLOINCMP); \
- util_out_print("!_!_at File offset : [0x!XL]", TRUE, file_offset); \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_LDSPANGLOINCMP, 1, &file_offset); \
if (sn_gvkey->end && expected_sn_chunk_number) \
{ \
sn_key_str_end = format_targ_key(&sn_key_str[0], MAX_ZWR_KEY_SZ, sn_gvkey, TRUE); \
@@ -149,7 +152,8 @@ error_def(ERR_LDSPANGLOINCMP);
#define DISPLAY_FILE_OFFSET_OF_RECORD_AND_REST_OF_BLOCK \
{ \
- util_out_print("!_!_File offset : [0x!XL]", TRUE, file_offset_base + ((unsigned char *)rp - ptr_base)); \
+ file_offset = file_offset_base + ((unsigned char *)rp - ptr_base); \
+ util_out_print("!_!_File offset : [0x!16 at XQ]", TRUE, &file_offset); \
util_out_print("!_!_Rest of Block :", TRUE); \
zwr_out_print((char *)rp, btop - (unsigned char *)rp); \
util_out_print(0, TRUE); \
@@ -235,7 +239,7 @@ void bin_load(uint4 begin, uint4 end)
rec_hdr *rp, *next_rp;
mval v, tmp_mval;
mname_entry gvname;
- mstr mstr_src, mstr_dest;
+ mstr mstr_src, mstr_dest, opstr;
collseq *extr_collseq, *db_collseq, *save_gv_target_collseq;
coll_hdr extr_collhdr, db_collhdr;
gv_key *tmp_gvkey = NULL; /* null-initialize at start, will be malloced later */
@@ -256,7 +260,12 @@ void bin_load(uint4 begin, uint4 end)
assert(4 == SIZEOF(coll_hdr));
gvinit();
v.mvtype = MV_STR;
- len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base);
+ len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base, DO_RTS_ERROR_FALSE);
+ if (0 >= len)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_LDBINFMT);
+ mupip_exit(ERR_LDBINFMT);
+ }
hdr_lvl = EXTR_HEADER_LEVEL(ptr);
if (!(((('4' == hdr_lvl) || ('5' == hdr_lvl)) && (V5_BIN_HEADER_SZ == len)) ||
(('6' == hdr_lvl) && (BIN_HEADER_SZ == len)) ||
@@ -320,11 +329,13 @@ void bin_load(uint4 begin, uint4 end)
# ifdef GTM_CRYPT
if ('7' <= hdr_lvl)
{
- encrypted_hash_array_len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base);
+ encrypted_hash_array_len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base,
+ DO_RTS_ERROR_TRUE);
encrypted_hash_array_ptr = malloc(encrypted_hash_array_len);
memcpy(encrypted_hash_array_ptr, ptr, encrypted_hash_array_len);
n_index = encrypted_hash_array_len / GTMCRYPT_HASH_LEN;
encr_key_handles = (gtmcrypt_key_t *)malloc(SIZEOF(gtmcrypt_key_t) * n_index);
+ memset(encr_key_handles, 0, SIZEOF(gtmcrypt_key_t) * n_index);
INIT_PROC_ENCRYPTION(NULL, gtmcrypt_errno);
GC_BIN_LOAD_ERR(gtmcrypt_errno);
for (index = 0; index < n_index; index++)
@@ -332,14 +343,14 @@ void bin_load(uint4 begin, uint4 end)
curr_hash_ptr = encrypted_hash_array_ptr + index * GTMCRYPT_HASH_LEN;
if (0 == memcmp(curr_hash_ptr, EMPTY_GTMCRYPT_HASH, GTMCRYPT_HASH_LEN))
continue;
- GTMCRYPT_GETKEY(NULL, curr_hash_ptr, encr_key_handles[index], gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(NULL, curr_hash_ptr, encr_key_handles[index], gtmcrypt_errno);
GC_BIN_LOAD_ERR(gtmcrypt_errno);
}
}
# endif
if ('2' < hdr_lvl)
{
- len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base);
+ len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base, DO_RTS_ERROR_TRUE);
if (SIZEOF(coll_hdr) != len)
{
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_TEXT, 2, RTS_ERROR_TEXT("Corrupt collation header"),
@@ -354,7 +365,7 @@ void bin_load(uint4 begin, uint4 end)
begin = 2;
for (iter = 2; iter < begin; iter++)
{
- if (!(len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base)))
+ if (!(len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base, DO_RTS_ERROR_TRUE)))
{
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_LOADEOF, 1, begin);
util_out_print("Error reading record number: !UL\n", TRUE, iter);
@@ -387,6 +398,8 @@ void bin_load(uint4 begin, uint4 end)
if (++rec_count > end)
break;
next_cmpc = 0;
+ if (mupip_error_occurred && ONERROR_STOP == onerror)
+ break;
mupip_error_occurred = FALSE;
if (mu_ctrly_occurred)
break;
@@ -399,7 +412,8 @@ void bin_load(uint4 begin, uint4 end)
util_out_print(0, TRUE);
mu_ctrlc_occurred = FALSE;
}
- if (!(len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base)) || mupip_error_occurred)
+ if (!(len = file_input_bin_get((char **)&ptr, &file_offset_base, (char **)&ptr_base, DO_RTS_ERROR_TRUE))
+ || mupip_error_occurred)
break;
else if (len == SIZEOF(coll_hdr))
{
@@ -442,6 +456,11 @@ void bin_load(uint4 begin, uint4 end)
* For globals that do span regions, "gv_cur_region" will be set just before the call to op_gvput.
* This value of "gvnh_reg" will be in effect until all records of this global are processed.
*/
+ if (mupip_error_occurred)
+ {
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_RECLOAD, 1, rec_count);
+ ONERROR_PROCESS;
+ }
max_key = gvnh_reg->gd_reg->max_key_size;
db_collhdr.act = gv_target->act;
db_collhdr.ver = gv_target->ver;
@@ -578,7 +597,9 @@ void bin_load(uint4 begin, uint4 end)
} else
TREF(transform) = FALSE;
/* convert the subscript to string format */
- end_buff = gvsub2str(src_buff, dest_buff, FALSE);
+ opstr.addr = (char *)dest_buff;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ end_buff = gvsub2str(src_buff, &opstr, FALSE);
/* transform the string to the current subsc format */
TREF(transform) = TRUE;
tmp_mval.mvtype = MV_STR;
@@ -758,22 +779,21 @@ void bin_load(uint4 begin, uint4 end)
}
if (max_data_len < v.str.len)
max_data_len = v.str.len;
- /* The below macro finishes the task of GV_BIND_NAME_AND_ROOT_SEARCH
- * (e.g. setting gv_cur_region for spanning globals).
- */
- GV_BIND_SUBSNAME_IF_GVSPAN(gvnh_reg, gd_header, gv_currkey, dummy_reg);
- bin_call_db(BIN_PUT, (INTPTR_T)&v, 0);
+ if (gvnh_reg->gvspan)
+ bin_call_db(BIN_PUT_GVSPAN, (INTPTR_T)&v, (INTPTR_T)gvnh_reg);
+ else
+ bin_call_db(BIN_PUT, (INTPTR_T)&v, 0);
if (mupip_error_occurred)
{
if (!mupip_DB_full)
{
bin_call_db(ERR_COR, (INTPTR_T)rec_count, (INTPTR_T)global_key_count);
file_offset = file_offset_base + ((unsigned char *)rp - ptr_base);
- util_out_print("!_!_at File offset : [0x!XL]", TRUE, file_offset);
+ util_out_print("!_!_at File offset : [0x!16 at XQ]", TRUE, &file_offset);
DISPLAY_CURRKEY;
DISPLAY_VALUE("!_!_Value :");
}
- break;
+ ONERROR_PROCESS;
}
if (putting_a_sn)
putting_a_sn = FALSE;
@@ -813,11 +833,21 @@ gvnh_reg_t *bin_call_db(int routine, INTPTR_T parm1, INTPTR_T parm2)
* subroutine due to the limitations of condition handlers and unwinding on UNIX
*/
gvnh_reg_t *gvnh_reg;
-
+ gd_region *dummy_reg;
gvnh_reg = NULL;
+
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
ESTABLISH_RET(mupip_load_ch, gvnh_reg);
switch(routine)
{
+ case BIN_PUT_GVSPAN:
+ /* The below macro finishes the task of GV_BIND_NAME_AND_ROOT_SEARCH
+ * (e.g. setting gv_cur_region for spanning globals).
+ */
+ gvnh_reg = (gvnh_reg_t *)parm2;
+ GV_BIND_SUBSNAME_IF_GVSPAN(gvnh_reg, gd_header, gv_currkey, dummy_reg);
+ /* WARNING: fall-through */
case BIN_PUT:
op_gvput((mval *)parm1);
break;
@@ -825,7 +855,7 @@ gvnh_reg_t *bin_call_db(int routine, INTPTR_T parm1, INTPTR_T parm2)
GV_BIND_NAME_AND_ROOT_SEARCH((gd_addr *)parm1, (mname_entry *)parm2, gvnh_reg);
break;
case ERR_COR:
- rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_CORRUPT, 2, parm1, parm2);
+ rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_CORRUPTNODE, 2, parm1, parm2);
case BIN_KILL:
gvcst_kill(FALSE);
break;
diff --git a/sr_unix/buildaux.csh b/sr_unix/buildaux.csh
index aa09c17..281ac7b 100644
--- a/sr_unix/buildaux.csh
+++ b/sr_unix/buildaux.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2013 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -29,15 +29,15 @@ set mach_type = `uname -m`
set platform_name = `uname | sed 's/-//g' | tr '[A-Z]' '[a-z]'`
if ( $1 == "" ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
endif
if ( $2 == "" ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
endif
if ( $3 == "" ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
endif
@@ -58,14 +58,14 @@ case "[pP]*":
breaksw
default:
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
breaksw
endsw
version $1 $2
-if ( $buildaux_status != 0 ) then
+if ( $buildaux_status ) then
echo "buildaux-I-usage, Usage: $shell buildaux.csh <version> <image type> <target directory> [auxillary]"
exit $buildaux_status
endif
@@ -95,7 +95,7 @@ if (4 <= $#) then
set new_auxillarylist = "$new_auxillarylist lke gtcm_gnp_server"
else if ( "$auxillary" == "gnpclient") then
$shell $gtm_tools/buildshr.csh $1 $2 ${gtm_root}/$1/$2
- if (0 != $status) @ buildaux_status = $status
+ if ($status) @ buildaux_status++
else if ( "$auxillary" == "gnpserver") then
set new_auxillarylist = "$new_auxillarylist gtcm_gnp_server"
else if ( "$auxillary" == "cmisockettcp") then
@@ -108,13 +108,10 @@ if (4 <= $#) then
set new_auxillarylist = "$new_auxillarylist gtcm_pkdisp gtcm_shmclean"
else if ("$auxillary" == "mumps") then
$shell $gtm_tools/buildshr.csh $1 $2 ${gtm_root}/$1/$2
- if (0 != $status) @ buildaux_status = $status
+ if ($status) @ buildaux_status++
if ($#argv == 4) then
exit $buildaux_status
endif
- else if ( "$auxillary" == "gtmrpc" || "$auxillary" == "gtm_svc") then
- $shell $gtm_tools/buildshr.csh $1 $2 ${gtm_root}/$1/$2
- if (0 != $status) @ buildaux_status = $status
else
set new_auxillarylist = "$new_auxillarylist $auxillary"
endif
@@ -138,7 +135,7 @@ else
if ( $buildaux_validexecutable == 0 && "$new_auxillarylist" != "" ) then
echo "buildaux-E-AuxUnknown -- Auxillary, ""$argv[4-]"", is not a valid one"
echo "buildaux-I-usage, Usage: $shell buildaux.csh <version> <image type> <target directory> [auxillary-list]"
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
exit $buildaux_status
endif
endif
@@ -186,8 +183,8 @@ if ( $buildaux_gde == 1 ) then
setenv LC_CTYPE C
setenv gtm_chset M
./mumps *.m
- if (0 != $status) @ buildaux_status = $status
- if ($buildaux_status != 0) then
+ if ($status) then
+ @ buildaux_status++
echo "buildaux-E-compile_M, Failed to compile .m programs in M mode" \
>> $gtm_log/error.${gtm_exe:t}.log
endif
@@ -210,8 +207,8 @@ if ( $buildaux_gde == 1 ) then
ln -s ../$mfile $mfile
end
../mumps *.m
- if (0 != $status) @ buildaux_status = $status
- if ($buildaux_status != 0) then
+ if ($status) then
+ @ buildaux_status++
echo "buildaux-E-compile_UTF8, Failed to compile .m programs in UTF-8 mode" \
>> $gtm_log/error.${gtm_exe:t}.log
endif
@@ -239,7 +236,7 @@ if ( $buildaux_dse == 1 ) then
$gt_ld_sysrtns $gt_ld_options_all_exe -ldse -lmumps -lstub \
$gt_ld_extra_libs $gt_ld_syslibs >& $gtm_map/dse.map
if ( $status != 0 || ! -x $3/dse ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkdse, Failed to link dse (see ${dollar_sign}gtm_map/dse.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -261,7 +258,7 @@ if ( $buildaux_geteuid == 1 ) then
gt_ld $gt_ld_options $aix_loadmap_option ${gt_ld_option_output}$3/geteuid -L$gtm_obj $gtm_obj/geteuid.o \
$gt_ld_sysrtns $gt_ld_extra_libs -lmumps $gt_ld_syslibs >& $gtm_map/geteuid.map
if ( $status != 0 || ! -x $3/geteuid ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkgeteuid, Failed to link geteuid (see ${dollar_sign}gtm_map/geteuid.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -284,7 +281,7 @@ if ( $buildaux_gtmsecshr == 1 ) then
gt_ld $gt_ld_options $aix_loadmap_option ${gt_ld_option_output}$3/${file} -L$gtm_obj $gtm_obj/${file}.o \
$gt_ld_sysrtns $gt_ld_extra_libs -lmumps $gt_ld_syslibs >& $gtm_map/${file}.map
if ( $status != 0 || ! -x $3/${file} ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-link${file}, Failed to link ${file} (see ${dollar_sign}gtm_map/${file}.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -304,7 +301,7 @@ if ( $buildaux_gtmsecshr == 1 ) then
cd utf8; ln -s ../gtmsecshrdir gtmsecshrdir; cd -
endif
$gtm_com/IGS $3/gtmsecshr "CHOWN" # make gtmsecshr, gtmsecshrdir, gtmsecshrdir/gtmsecshr files/dirs root owned
- if (0 != $status) @ buildaux_status = $status
+ if ($status) @ buildaux_status++
endif
if ( $buildaux_lke == 1 ) then
@@ -316,7 +313,7 @@ if ( $buildaux_lke == 1 ) then
$gt_ld_sysrtns $gt_ld_options_all_exe -llke -lmumps -lgnpclient -lmumps -lgnpclient -lcmisockettcp \
$gt_ld_extra_libs $gt_ld_syslibs >& $gtm_map/lke.map
if ( $status != 0 || ! -x $3/lke ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linklke, Failed to link lke (see ${dollar_sign}gtm_map/lke.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -337,7 +334,7 @@ if ( $buildaux_mupip == 1 ) then
$gt_ld_sysrtns $gt_ld_options_all_exe -lmupip -lmumps -lstub \
$gt_ld_extra_libs $gt_ld_aio_syslib $gt_ld_syslibs >& $gtm_map/mupip.map
if ( $status != 0 || ! -x $3/mupip ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkmupip, Failed to link mupip (see ${dollar_sign}gtm_map/mupip.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -360,7 +357,7 @@ if ( $buildaux_gtcm_server == 1 ) then
$gtm_obj/gtcm_main.o $gtm_obj/omi_srvc_xct.o $gt_ld_sysrtns $gt_ld_options_all_exe \
-lgtcm -lmumps -lstub $gt_ld_extra_libs $gt_ld_syslibs >& $gtm_map/gtcm_server.map
if ( $status != 0 || ! -x $3/gtcm_server) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkgtcm_server, Failed to link gtcm_server (see ${dollar_sign}gtm_map/gtcm_server.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -384,7 +381,7 @@ if ( $buildaux_gtcm_gnp_server == 1 ) then
-lgnpserver -llke -lmumps -lcmisockettcp -lstub \
$gt_ld_extra_libs $gt_ld_syslibs >& $gtm_map/gtcm_gnp_server.map
if ( $status != 0 || ! -x $3/gtcm_gnp_server) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkgtcm_gnp_server, Failed to link gtcm_gnp_server" \
"(see ${dollar_sign}gtm_map/gtcm_gnp_server.map)" >> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -408,7 +405,7 @@ if ( $buildaux_gtcm_play == 1 ) then
$gtm_obj/gtcm_play.o $gtm_obj/omi_sx_play.o $gt_ld_sysrtns $gt_ld_options_all_exe \
-lgtcm -lmumps -lstub $gt_ld_extra_libs $gt_ld_syslibs >& $gtm_map/gtcm_play.map
if ( $status != 0 || ! -x $3/gtcm_play) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkgtcm_play, Failed to link gtcm_play (see ${dollar_sign}gtm_map/gtcm_play.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -431,7 +428,7 @@ if ( $buildaux_gtcm_pkdisp == 1 ) then
$gt_ld_sysrtns -lgtcm -lmumps -lstub $gt_ld_extra_libs $gt_ld_syslibs \
>& $gtm_map/gtcm_pkdisp.map
if ( $status != 0 || ! -x $3/gtcm_pkdisp) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkgtcm_pkdisp, Failed to link gtcm_pkdisp (see ${dollar_sign}gtm_map/gtcm_pkdisp.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -452,7 +449,7 @@ if ( $buildaux_gtcm_shmclean == 1 ) then
$gt_ld_sysrtns -lgtcm -lmumps -lstub $gt_ld_extra_libs $gt_ld_syslibs \
>& $gtm_map/gtcm_shmclean.map
if ( $status != 0 || ! -x $3/gtcm_shmclean) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkgtcm_shmclean, Failed to link gtcm_shmclean (see ${dollar_sign}gtm_map/gtcm_shmclean.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -472,7 +469,7 @@ if ( $buildaux_semstat2 == 1 ) then
gt_ld $gt_ld_options $aix_loadmap_option ${gt_ld_option_output}$3/semstat2 -L$gtm_obj $gtm_obj/semstat2.o \
$gt_ld_sysrtns $gt_ld_extra_libs $gt_ld_syslibs >& $gtm_map/semstat2.map
if ( $status != 0 || ! -x $3/semstat2 ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linksemstat2, Failed to link semstat2 (see ${dollar_sign}gtm_map/semstat2.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -490,7 +487,7 @@ if ( $buildaux_ftok == 1 ) then
gt_ld $gt_ld_options $aix_loadmap_option ${gt_ld_option_output}$3/ftok -L$gtm_obj $gtm_obj/ftok.o \
$gt_ld_sysrtns -lmumps $gt_ld_extra_libs $gt_ld_syslibs >& $gtm_map/ftok.map
if ( $status != 0 || ! -x $3/ftok ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkftok, Failed to link ftok (see ${dollar_sign}gtm_map/ftok.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -511,7 +508,7 @@ if ( $buildaux_dbcertify == 1 ) then
$gtm_obj/{dbcertify,dbcertify_cmd}.o $gt_ld_sysrtns -ldbcertify -lmupip -lmumps -lstub $gt_ld_aio_syslib \
$gt_ld_extra_libs $gt_ld_syslibs >& $gtm_map/dbcertify.map
if ( $status != 0 || ! -x $3/dbcertify ) then
- set buildaux_status = `expr $buildaux_status + 1`
+ @ buildaux_status++
echo "buildaux-E-linkdbcertify, Failed to link dbcertify (see ${dollar_sign}gtm_map/dbcertify.map)" \
>> $gtm_log/error.${gtm_exe:t}.log
else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
@@ -540,7 +537,7 @@ if ($buildaux_gtmcrypt == 1) then
breaksw
endsw
# First copy all the necessary source and script files to $gtm_dist/plugin/gtmcrypt
- set helpers = "add_db_key,encrypt_sign_db_key,gen_keypair,gen_sym_hash,gen_sym_key,import_and_sign_key"
+ set helpers = "encrypt_sign_db_key,gen_keypair,gen_sym_hash,gen_sym_key,import_and_sign_key"
set helpers = "$helpers,pinentry-gtm,show_install_config"
set srcfiles = "gtmcrypt_dbk_ref.c gtmcrypt_pk_ref.c gtmcrypt_sym_ref.c gtmcrypt_ref.c gtm_tls_impl.c maskpass.c"
@@ -573,9 +570,9 @@ if ($buildaux_gtmcrypt == 1) then
# okay since pfloyd is AIX 5.3 which isn't a supported AIX version anyways.
set host=$HOST:r:r:r
if ($host !~ pfloyd) then
- $make gtmtls
- if (0 != $status) then
- set buildaux_status = `expr $buildaux_status + 1`
+ $make gtmtls image=$plugin_build_type
+ if ($status) then
+ @ buildaux_status++
echo "buildaux-E-tls, failed to build libgtmtls.so." >> $gtm_log/error.${gtm_exe:t}.log
endif
endif
@@ -592,19 +589,18 @@ if ($buildaux_gtmcrypt == 1) then
if ("gcrypt" == "$supported_lib" && "BLOWFISHCFB" == "$algorithm") continue
echo "####### Building encryption plugin using $supported_lib with $algorithm algorithm #########"
$make gtmcrypt image=$plugin_build_type thirdparty=$supported_lib algo=$algorithm $fips_flag
- set bstat = $status
- echo ""
- if (0 != $bstat) then
- set buildaux_status = `expr $buildaux_status + 1`
+ if ($status) then
+ @ buildaux_status++
echo "buildaux-E-libgtmcrypt, failed to build gtmcrypt and/or helper scripts." \
>> $gtm_log/error.${gtm_exe:t}.log
endif
+ echo ""
end
end
# Now that the individual libraries are built, go ahead and build the maskpass
$make maskpass
- if (0 != $status) then
- set buildaux_status = `expr $buildaux_status + 1`
+ if ($status) then
+ @ buildaux_status++
echo "buildaux-E-maskpass, failed to build maskpass." >> $gtm_log/error.${gtm_exe:t}.log
endif
#
@@ -619,7 +615,7 @@ if ($buildaux_gtmcrypt == 1) then
else
# Now that we've built "possibly" more than one encryption library, choose one configuration (based on
# third-party library and algorithm) randomly and install that.
- set rand = `$gtm_dist/mumps -run %XCMD 'write 1+$random('$#supported_list')'`
+ set rand = `echo $#supported_list | awk '{srand() ; print 1+int(rand()*$1)}'`
set encryption_lib = $supported_list[$rand]
if ("gcrypt" == "$encryption_lib") then
# Force AES as long as the plugin is linked against libgcrypt
@@ -628,13 +624,13 @@ if ($buildaux_gtmcrypt == 1) then
# OpenSSL, V9* build. Go ahead and randomize the algorithm
# increase probability of AES256CFB, the industry standard and the one we officially support
set algorithms = ("AES256CFB" "AES256CFB" "BLOWFISHCFB")
- set rand = `$gtm_dist/mumps -run %XCMD 'write 1+$random('$#algorithms')'`
+ set rand = `echo $#algorithms | awk '{srand() ; print 1+int(rand()*$1)}'`
set algorithm = $algorithms[$rand]
endif
endif
$make install thirdparty=$encryption_lib algo=$algorithm
- if (0 != $status) then
- set buildaux_status = `expr $buildaux_status + 1`
+ if ($status) then
+ @ buildaux_status++
echo "buildaux-E-libgtmcrypt, failed to install libgtmcrypt and/or helper scripts" \
>> $gtm_log/error.${gtm_exe:t}.log
endif
diff --git a/sr_unix/buildshr.csh b/sr_unix/buildshr.csh
index e1fd8e3..55d082b 100644
--- a/sr_unix/buildshr.csh
+++ b/sr_unix/buildshr.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2010 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -144,24 +144,6 @@ else if ( "ia64" == $mach_type && "hpux" == $platform_name ) then
endif
endif
-# Note: gtm_svc should link with gtm_dal_svc.o before gtm_mumps_call_clnt.o(libgtmrpc.a) to
-# resolve conflicting symbols (gtm_init_1, gtm_halt_1 etc..) appropriately.
-if ( $gt_ar_gtmrpc_name != "" ) then
- set aix_loadmap_option = ''
- if ( $HOSTOS == "AIX") then
- set aix_loadmap_option = "-bloadmap:$gtm_map/gtmsvc.loadmap"
- endif
- # export gtm_filename_to_id and dependent modules from gtm_svc.
- gt_ld $gt_ld_options $gt_ld_options_all_exe $aix_loadmap_option ${gt_ld_option_output}$3/gtm_svc \
- -L$gtm_obj $gtm_obj/{gtm_svc,gtm_rpc_init,gtm_dal_svc}.o $gt_ld_sysrtns -lmumps -lgnpclient \
- $gt_ld_extra_libs -lcmisockettcp -L$gtm_exe -l$gt_ar_gtmrpc_name $gt_ld_syslibs >& $gtm_map/gtm_svc.map
- if ( $status != 0 || ! -x $3/gtm_svc ) then
- set buildshr_status = `expr $buildshr_status + 1`
- echo "buildshr-E-linkgtm_svc, Failed to link gtm_svc (see ${dollar_sign}gtm_map/gtm_svc.map)" \
- >> $gtm_log/error.`basename $gtm_exe`.log
- endif
-endif
-
unset echo
if ( $buildshr_verbose == "0" ) then
unset verbose
diff --git a/sr_unix/check_unicode_support.csh b/sr_unix/check_unicode_support.csh
index a59ef7c..553ac3c 100644
--- a/sr_unix/check_unicode_support.csh
+++ b/sr_unix/check_unicode_support.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2007, 2013 Fidelity Information Services, Inc #
+# Copyright 2007, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -30,24 +30,24 @@ endif
# ssh <some host> ls -l {/usr/local,/usr,}/lib{64,,32}/libicuio.{a,so,sl}
foreach libdir ( {/usr/local,/usr,}/lib{64,/x86_64-linux-gnu,,32,/i386-linux-gnu}/libicuio.{a,so,sl} )
- # 36 is the least version GT.M supports for ICU.
- # We have to get the numeric value from the ICU library. On non-AIX platforms, this can be done by
- # first getting the library to which libicuio.so is pointing to (this is always TRUE, in the sense
- # ICU always ships libicuio.so linked to the appropriate version'ed library).
- # The ICU libraries are formatted like "libicu<ALPHANUM>.<EXT>.<MAJOR_VER><MINOR_VER>". So, we can
- # use awk to get the last part of the 'ls -l' on libicuio.so and use awk and cut to get the version
- # numbers. However on AIX and z/OS, ICU libraries are formatted like "libicu<ALPHANUM><MAJOR_VER><MINOR_VER>.<EXT>"
- # and hence it is not as straightforward to extract the MAJOR_VER. So, we first eliminate the prefix
- # part of the library name that contains libicu<ALPHANUM> using sed and use cut now to extract the
- # version number.
+ # 36 is the least version GT.M supports for ICU. We have to get the numeric value from the ICU library.
+ # ICU ships libicuio.so linked to the appropriate versioned library - so using filetype -L works well
+ # The below is the format of the libraries on various platforms:
+ # AIX, z/OS : libicu<alphanum><majorver><minorver>.<ext> (e.g libicuio42.1.a)
+ # Others : libicu<alphanum>.<ext>.<majorver>.<minorver> (e.g libicuio.so.42.1)
+
if ( ! -l $libdir ) continue
- set icu_versioned_lib = `ls -l $libdir | awk '{print $NF}'`
+ set icu_versioned_lib = `filetest -L $libdir`
+ set verinfo = ${icu_versioned_lib:s/libicuio//}
+ set parts = ( ${verinfo:as/./ /} )
if ($HOSTOS == "AIX" || $HOSTOS == "OS/390") then
- set icu_ver = `echo $icu_versioned_lib | sed 's/libicuio//g' | cut -f 1 -d '.'`
+ # for the above example parts = (42 1 a)
+ set icu_ver = $parts[1]
else
- set icu_ver = `echo $icu_versioned_lib | cut -f 3 -d '.'`
+ # for the above example parts = (so 42 1)
+ set icu_ver = $parts[2]
endif
if ($icu_ver >= "36") then
diff --git a/sr_unix/cli.c b/sr_unix/cli.c
index 43b055b..304624f 100644
--- a/sr_unix/cli.c
+++ b/sr_unix/cli.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -246,7 +246,11 @@ boolean_t cli_get_str(char *entry, char *dst, unsigned short *max_len)
char buf[MAX_LINE];
char local_str[MAX_LINE];
size_t maxdstlen, maxbuflen, copylen;
+# ifdef DEBUG
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
+# endif
maxbuflen = SIZEOF(buf);
maxdstlen = *max_len;
@@ -256,12 +260,16 @@ boolean_t cli_get_str(char *entry, char *dst, unsigned short *max_len)
assert(strlen(entry) > 0);
strncpy(local_str, entry, SIZEOF(local_str) - 1);
- if (!(cli_present(local_str) == CLI_PRESENT
- && cli_get_value(local_str, buf)))
+ DEBUG_ONLY(TREF(cli_get_str_max_len) = maxdstlen;) /* for use inside cli_get_value -> get_parm_entry ... */
+ if (!((CLI_PRESENT == cli_present(local_str)) && cli_get_value(local_str, buf)))
{
if (!cli_get_parm(local_str, buf))
+ {
+ DEBUG_ONLY(TREF(cli_get_str_max_len) = 0;) /* for use inside cli_get_value -> get_parm_entry ... */
return FALSE;
+ }
}
+ DEBUG_ONLY(TREF(cli_get_str_max_len) = 0;) /* for use inside cli_get_value -> get_parm_entry ... */
copylen = strlen(buf);
copylen = MIN(copylen, maxdstlen);
memset(dst, 0, maxdstlen);
diff --git a/sr_unix/cli_lex.c b/sr_unix/cli_lex.c
index 4840889..e3b652d 100644
--- a/sr_unix/cli_lex.c
+++ b/sr_unix/cli_lex.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -47,24 +47,17 @@ GBLREF boolean_t gtm_utf8_mode;
#define CLI_ISSPACE(CHAR) ISSPACE_ASCII(CHAR)
#endif
-/* Don't use toupper() because, with Turkish unicode settings, toupper('i') does not have well-defined behavior. On some platforms
- * it returns back 'i' itself. This is because, in Turkish, the actual uppercase version of 'i' is 'I' with a dot on top, which is
- * not an ascii character. Thus cli_strupper would incorrectly convert some qualifiers, resulting in CLIERR errors. For example it
- * would convert "-dynamic_literals" to "-DYNAMiC_LiTERALS" or "-warnings" to "-WARNiNGS".
- */
-#define CLI_TOUPPER(C) (('a' <= (C) && (C) <= 'z') ? ((C) + ('A' - 'a')) : (C))
-
static int tok_string_extract(void)
{
int token_len;
boolean_t have_quote, first_quote;
uchar_ptr_t in_sp, out_sp, in_next, last_in_next,
bufend; /* really one past last byte of buffer */
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
wint_t ch;
-#else
+# else
int ch;
-#endif
+# endif
assert(cli_lex_in_ptr);
in_sp = (uchar_ptr_t)cli_lex_in_ptr->tp;
@@ -151,12 +144,12 @@ void cli_lex_setup (int argc, char **argv)
{
int parmlen, parmindx;
char **parmptr;
-#ifdef __osf__
-#pragma pointer_size (restore)
-#endif
-#ifdef KEEP_zOS_EBCDIC
+# ifdef __osf__
+# pragma pointer_size (restore)
+# endif
+# ifdef KEEP_zOS_EBCDIC
__argvtoascii_a(argc, argv);
-#endif
+# endif
cmd_cnt = argc;
cmd_arg = (char **)argv;
/* Quickly run through the parameters to get a ballpark on the
@@ -211,7 +204,7 @@ void cli_strupper(char *sp)
int c;
while (c = *sp)
- *sp++ = IS_ASCII(c) ? CLI_TOUPPER(c) : c;
+ *sp++ = TOUPPER(c);
}
/*
@@ -227,12 +220,10 @@ int cli_is_hex(char *p)
{
if (('+' == *p) || ('-' == *p))
p++;
-
- if (('0' == *p) && ('X' == CLI_TOUPPER(*(p + 1))))
+ if (('0' == *p) && ('X' == TOUPPER(*(p + 1))))
{
p = p + 2;
}
-
while (*p && ISXDIGIT_ASCII(*p))
p++;
@@ -281,14 +272,14 @@ int cli_is_assign(char *p)
void skip_white_space(void)
{
uchar_ptr_t in_sp;
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
wint_t ch;
uchar_ptr_t next_sp, bufend;
-#endif
+# endif
assert(cli_lex_in_ptr);
in_sp = (uchar_ptr_t)cli_lex_in_ptr->tp;
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
if (gtm_utf8_mode)
{
bufend = (uchar_ptr_t)(cli_lex_in_ptr->in_str + cli_lex_in_ptr->buflen);
@@ -323,11 +314,11 @@ static int tok_extract (void)
{
int token_len;
uchar_ptr_t in_sp, in_next, out_sp, bufend;
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
wint_t ch;
-#else
+# else
int ch;
-#endif
+# endif
assert(cli_lex_in_ptr);
skip_white_space(); /* Skip leading blanks */
@@ -336,7 +327,6 @@ static int tok_extract (void)
out_sp = (uchar_ptr_t)cli_token_buf;
token_len = 0;
-
in_next = CLI_GET_CHAR(in_sp, bufend, ch);
if ('-' == ch || '=' == ch)
{
@@ -359,7 +349,6 @@ static int tok_extract (void)
ch = 0;
out_sp = CLI_PUT_CHAR(out_sp, ch);
cli_lex_in_ptr->tp = (char *)in_sp;
-
return(token_len);
}
@@ -379,7 +368,7 @@ char *cli_fgets(char *buffer, int buffersize, FILE *fp, boolean_t cli_lex_str)
{
size_t in_len;
char cli_fgets_buffer[MAX_LINE], *destbuffer, *retptr;
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
int mbc_len, u16_off, destsize;
int32_t mbc_dest_len;
UErrorCode errorcode;
@@ -387,9 +376,9 @@ char *cli_fgets(char *buffer, int buffersize, FILE *fp, boolean_t cli_lex_str)
UChar32 uc32_cp;
UChar cli_fgets_Ubuffer[MAX_LINE];
UFILE *u_fp;
-#endif
+# endif
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
if (gtm_utf8_mode)
{
cli_fgets_Ubuffer[0] = 0;
@@ -457,7 +446,7 @@ char *cli_fgets(char *buffer, int buffersize, FILE *fp, boolean_t cli_lex_str)
cli_lex_in_ptr->tp = NULL;
} else
{
-#endif
+# endif
cli_fgets_buffer[0] = '\0';
FGETS_FILE(cli_fgets_buffer, SIZEOF(cli_fgets_buffer), fp, retptr);
if (NULL != retptr)
@@ -481,10 +470,9 @@ char *cli_fgets(char *buffer, int buffersize, FILE *fp, boolean_t cli_lex_str)
cli_lex_in_ptr->tp = destbuffer;
} else if (cli_lex_str)
cli_lex_in_ptr->tp = NULL;
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
}
-#endif
-
+# endif
return retptr;
}
@@ -524,8 +512,6 @@ int cli_gettoken (int *eof)
strcat(cli_lex_in_ptr->in_str, cli_lex_in_ptr->argv[arg_no++]);
}
}
-
-
if (NULL == cli_lex_in_ptr->tp || strlen(cli_lex_in_ptr->tp) < 1)
{
cli_token_buf[0] = '\0';
@@ -534,16 +520,14 @@ int cli_gettoken (int *eof)
* writing to freed memory if the set were done here.
*/
cli_fgets(cli_lex_in_ptr->in_str, MAX_LINE, stdin, TRUE);
- if (NULL != cli_lex_in_ptr->tp)
- *eof = 0;
- else
- {
- *eof = EOF;
- return (0);
- }
-
+ if (NULL != cli_lex_in_ptr->tp)
+ *eof = 0;
+ else
+ {
+ *eof = EOF;
+ return (0);
+ }
}
-
token_len = tok_extract();
*eof = (cli_lex_in_ptr->argc > 1 && token_len == 0);
return token_len;
@@ -570,11 +554,9 @@ int cli_look_next_token(int *eof)
assert(cli_lex_in_ptr);
if (((char *) NULL == cli_lex_in_ptr->tp) || (!strlen(cli_lex_in_ptr->tp)))
return(0);
-
old_tp = cli_lex_in_ptr->tp;
tok_len = cli_gettoken(eof);
cli_lex_in_ptr->tp = old_tp;
-
return(tok_len);
}
@@ -586,11 +568,9 @@ int cli_look_next_string_token(int *eof)
assert(cli_lex_in_ptr);
if (!strlen(cli_lex_in_ptr->tp))
return(0);
-
old_tp = cli_lex_in_ptr->tp;
tok_len = cli_get_string_token(eof);
cli_lex_in_ptr->tp = old_tp;
-
return(tok_len);
}
@@ -630,7 +610,6 @@ int cli_get_string_token(int *eof)
strcat(cli_lex_in_ptr->in_str, cli_lex_in_ptr->argv[arg_no++]);
}
}
-
if (NULL == cli_lex_in_ptr->tp || strlen(cli_lex_in_ptr->tp) < 1)
{
cli_token_buf[0] = '\0';
@@ -639,21 +618,19 @@ int cli_get_string_token(int *eof)
* writing to freed memory if the set were done here.
*/
cli_fgets(cli_lex_in_ptr->in_str, MAX_LINE, stdin, TRUE);
- if (NULL != cli_lex_in_ptr->tp)
- *eof = 0;
- else
+ if (NULL != cli_lex_in_ptr->tp)
+ *eof = 0;
+ else
{
*eof = EOF;
return (0);
}
- }
-
+ }
token_len = tok_string_extract();
*eof = (cli_lex_in_ptr->argc > 1 && token_len == 0);
return token_len;
}
-
/*
* -------------------------------------------------------
* Check if string has space in it
@@ -665,7 +642,7 @@ int cli_get_string_token(int *eof)
*/
int cli_has_space(char *p)
{
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
uchar_ptr_t local_p, next_p, bufend;
wint_t ch;
@@ -683,11 +660,8 @@ int cli_has_space(char *p)
p = (char *)local_p;
}
else
-#endif
+# endif
while (*p && !ISSPACE_ASCII(*p))
p++;
-
return ((*p) ? (TRUE) : (FALSE));
}
-
-
diff --git a/sr_unix/cli_parse.c b/sr_unix/cli_parse.c
index bbdc995..62d677c 100644
--- a/sr_unix/cli_parse.c
+++ b/sr_unix/cli_parse.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,6 +21,7 @@
#include "cli_parse.h"
#include "error.h"
#include "cli_disallow.h"
+#include "gtmio.h"
#define NO_STRING "NO"
@@ -910,7 +911,13 @@ bool cli_get_value(char *entry, char val_buf[])
{
CLI_ENTRY *pparm;
char local_str[MAX_LINE];
+# ifdef DEBUG
+ int ind, len;
+ CLI_ENTRY *parm_vals;
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
+# endif
strncpy(local_str, entry, SIZEOF(local_str) - 1);
cli_strupper(local_str);
if (NULL == (pparm = get_parm_entry(local_str)))
@@ -918,7 +925,24 @@ bool cli_get_value(char *entry, char val_buf[])
if (!pparm->present || NULL == pparm->pval_str)
return (FALSE);
else
+ {
+# ifdef DEBUG
+ if (TREF(cli_get_str_max_len) && (NULL != (parm_vals = pparm->qual_vals)))
+ {
+ for (ind = 0; ; ind++)
+ {
+ len = strlen(parm_vals[ind].name);
+ if (!len)
+ break;
+ /* Assert that we have allocated enough space to store all possible values for this parameter.
+ * If this assert fails, fix caller of cli_get_str to allocate enough space.
+ */
+ assert(len <= TREF(cli_get_str_max_len));
+ }
+ }
+# endif
strcpy(val_buf, pparm->pval_str);
+ }
return (TRUE);
}
@@ -985,7 +1009,7 @@ bool cli_get_parm(char *entry, char val_buf[])
return FALSE;
/* If no value and required, prompt for it */
PRINTF("%s", (gpcmd_parm_vals + match_ind)->prompt);
- fflush(stdout);
+ FFLUSH(stdout);
gets_res = cli_fgets(local_str, MAX_LINE, stdin, FALSE);
if (gets_res)
{
@@ -1026,7 +1050,7 @@ bool cli_get_parm(char *entry, char val_buf[])
if (MAX_LINE < parm_len)
{
PRINTF("Parameter string too long\n");
- fflush(stdout);
+ FFLUSH(stdout);
return (FALSE);
}
TAREF1(parm_str_len, match_ind) = parm_len;
diff --git a/sr_unix/comlist.csh b/sr_unix/comlist.csh
index bbf7fcf..3d4a0a7 100644
--- a/sr_unix/comlist.csh
+++ b/sr_unix/comlist.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2013 Fidelity Infromation Services, Inc #
+# Copyright 2001, 2014 Fidelity Infromation Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -231,7 +231,8 @@ else
endif
# Remove old error log.
-rm $gtm_log/error.`basename $gtm_exe`.log
+set errorlog = "$gtm_log/error.`basename $gtm_exe`.log"
+rm $errorlog
echo ""
@@ -380,8 +381,7 @@ if ( -x $gtm_root/$gtm_curpro/pro/mumps ) then
$gtm_root/$gtm_curpro/pro/mumps -run msg $i Unix
if ( ! -f ${j}_ctl.c ) then
- echo "comlist-E-MSGfail, MSG.m failed to produce output file ${j}_ctl.c" \
- >> $gtm_log/error.`basename $gtm_exe`.log
+ echo "comlist-E-MSGfail, MSG.m failed to produce output file ${j}_ctl.c" >> $errorlog
endif
if ( -f ${j}_ansi.h ) then
mv -f ${j}_ansi.h $gtm_inc
@@ -397,8 +397,7 @@ if ( -x $gtm_root/$gtm_curpro/pro/mumps ) then
unset real_gtm_dist
popd
else
- echo "comlist-E-NoMUMPS, unable to regenerate merrors.c and ttt.c due to missing $gtm_curpro/pro/mumps" \
- >> $gtm_log/error.`basename $gtm_exe`.log
+ echo "comlist-E-NoMUMPS, unable to regenerate merrors.c and ttt.c due to missing $gtm_curpro/pro/mumps" >> $errorlog
endif
#############################################################
@@ -555,19 +554,6 @@ foreach i ( $comlist_liblist )
echo "" >> ar$i.log
switch ( $i )
- case "gtmrpc":
- # Note: libgtmrpc.a must be built in $gtm_exe because it must also be shipped with the release.
- gt_ar $gt_ar_option_create $gtm_exe/lib$i.a `sed -f $gtm_tools/lib_list_ar.sed $gtm_tools/lib$i.list` >>& ar$i.log
- if ( 0 != $status ) then
- @ comlist_status = $status
- echo "comlist-E-ar${i}error, Error creating lib$i.a archive (see ${dollar_sign}gtm_obj/ar$i.log)" \
- >> $gtm_log/error.`basename $gtm_exe`.log
- endif
- # retain_list.txt contains modules listed in *.list that also need to be
- # included in libmumps.a (eg. getmaxfds, gtm_mumps_call_xdr)
- rm -f `sed -f $gtm_tools/lib_list_ar.sed $gtm_tools/lib$i.list |egrep -v -f $gtm_tools/retain_list.txt`
- breaksw
-
case "mumps":
# (Almost) everything else goes into libmumps.a, but the list is too long for a single command line so use xargs.
# This case must be executed last in the switch statement (because it picks up "everything else") and, hence,
@@ -580,8 +566,7 @@ foreach i ( $comlist_liblist )
# Exclude files that define the same externals
# (e.g., "main" and the VMS CLI [command line interpreter] emulator arrays):
- set exclude = "^gtm\.o|^gtm_main\.o|^gtm_svc\.o|^gtm_dal_svc\.o|^gtm_rpc_init\.o"
- set exclude = "$exclude|^lke\.o|^lke_cmd\.o|^dse\.o|^dse_cmd\.o|^dbcertify\.o"
+ set exclude = "^gtm\.o|^gtm_main\.o|^lke\.o|^lke_cmd\.o|^dse\.o|^dse_cmd\.o|^dbcertify\.o"
set exclude = "$exclude|^mupip\.o|^mupip_cmd\.o|^gtmsecshr\.o|^gtmsecshr_wrapper\.o|^geteuid\.o|^dtgbldir\.o"
set exclude = "$exclude|^semstat2\.o|^ftok\.o|^msg\.o|^gtcm_main\.o|^gtcm_play\.o|^gtcm_pkdisp\.o|^gtcm_shmclean\.o"
set exclude = "$exclude|^omi_srvc_xct\.o|^omi_sx_play\.o"
@@ -589,23 +574,21 @@ foreach i ( $comlist_liblist )
set exclude = "$exclude|^dummy_gtmci\.o"
/bin/ls | egrep '\.o$' | egrep -v "$exclude" | \
xargs -n50 $shell $gtm_tools/gt_ar.csh $gt_ar_option_create lib$i.a >>& ar$i.log
- if ( 0 != $status ) then
- @ comlist_status = $status
+ if ( $status ) then
+ @ comlist_status++
echo "comlist-E-ar${i}error, Error creating lib$i.a archive (see ${dollar_sign}gtm_obj/ar$i.log)" \
- >> $gtm_log/error.`basename $gtm_exe`.log
+ >> $errorlog
endif
breaksw
default:
gt_ar $gt_ar_option_create lib$i.a `sed -f $gtm_tools/lib_list_ar.sed $gtm_tools/lib$i.list` >>& ar$i.log
- if ( 0 != $status ) then
- @ comlist_status = $status
+ if ( $status ) then
+ @ comlist_status++
echo "comlist-E-ar${i}error, Error creating lib$i.a archive (see ${dollar_sign}gtm_obj/ar$i.log)" \
- >> $gtm_log/error.`basename $gtm_exe`.log
+ >> $errorlog
endif
- # retain_list.txt contains modules listed in *.list that also need to be
- # included in libmumps.a (eg. getmaxfds, gtm_mumps_call_xdr)
- rm -f `sed -f $gtm_tools/lib_list_ar.sed $gtm_tools/lib$i.list |egrep -v -f $gtm_tools/retain_list.txt`
+ rm -f `sed -f $gtm_tools/lib_list_ar.sed $gtm_tools/lib$i.list`
breaksw
endsw
@@ -632,39 +615,32 @@ switch ( $3 )
case "gtm_bta":
set bldtype = "Bta"
$shell $gtm_tools/buildbta.csh $p4
- if (0 != $status) @ comlist_status = $status # done before each breaksw instead of after endsw
- breaksw # as $status seems to be get reset in between
+ if ($status) @ comlist_status++ # done before each breaksw instead of after endsw
+ breaksw # as $status seems to be get reset in between
case "gtm_dbg":
set bldtype = "Dbg"
$shell $gtm_tools/builddbg.csh $p4
- if (0 != $status) @ comlist_status = $status
+ if ($status) @ comlist_status++
breaksw
case "gtm_pro":
set bldtype = "Pro"
$shell $gtm_tools/buildpro.csh $p4
- if (0 != $status) @ comlist_status = $status
+ if ($status) @ comlist_status++
breaksw
endsw
if ( ! -x $gtm_dist/mumps ) then
- echo "comlist-E-nomumps, ${dollar_sign}gtm_dist/mumps is not executable" >> $gtm_log/error.`basename $gtm_exe`.log
- echo "comlist-W-nomsgverify, unable to verify error message definition files" >> $gtm_log/error.`basename $gtm_exe`.log
- echo "comlist-W-noonlinehelp, unable to generate on-line help files" >> $gtm_log/error.`basename $gtm_exe`.log
+ echo "comlist-E-nomumps, ${dollar_sign}gtm_dist/mumps is not executable" >> $errorlog
+ echo "comlist-W-nomsgverify, unable to verify error message definition files" >> $errorlog
+ echo "comlist-W-noonlinehelp, unable to generate on-line help files" >> $errorlog
goto comlist.END
endif
set mupip_size = `ls -l $gtm_exe/mupip |awk '{print $5}'`
set gtmshr_size = `ls -l $gtm_exe/libgtmshr$gt_ld_shl_suffix |awk '{print $5}'`
-if ( "$HOSTOS" != "SunOS" ) then
- if ($mupip_size > $gtmshr_size) then
- echo "comlist-E-mupip_size, ${dollar_sign}gtm_dist/mupip is larger than ${dollar_sign}gtm_dist/libgtmshr$gt_ld_shl_suffix" \
- >> $gtm_log/error.`basename $gtm_exe`.log
- endif
-endif
-
cd $p3
# Generate Special Debug Files (z/OS specific at the moment)
@@ -694,12 +670,12 @@ if ((0 != $savestatus) || (! -e GTMDefinedTypesInit.m)) then
set errmsg = "COMLIST-E-FAIL gengtmdeftypes.csh failed to create GTMDefinedTypesInit.m "
set errmsg = "$errmsg - see log in $gtm_obj/gengtmdeftypes.log"
if (`expr $gtm_verno \< V900`) then
- @ comlist_status = $savestatus # No errors for development - this fails the build
+ @ comlist_status++ # No errors for development - this fails the build
else
echo "Warning: Build of $gtm_verno on $HOST, $errmsg" | \
mailx -s "${HOST}: Build for $gtm_verno failed to create GTMDefinedTypes.m" $USER
endif
- echo $errmsg >> $gtm_log/error.`basename $gtm_exe`.log
+ echo $errmsg >> $errorlog
endif
if (-e GTMDefinedTypesInit.m) then
# Need a different name for each build type as they can be different
@@ -707,16 +683,15 @@ if (-e GTMDefinedTypesInit.m) then
setenv LC_CTYPE C
setenv gtm_chset M
./mumps GTMDefinedTypesInit.m
- @ savestatus = $status
- if (0 != $savestatus) then
+ if ($status) then
set errmsg = "COMLIST-E-FAIL Failed to compile generated $gtm_exe/GTMDefinedTypes.m"
if (`expr $gtm_verno \< V900`) then
- @ comlist_status = $savestatus
+ @ comlist_status++
else
echo "Warning: During build of $gtm_verno on $HOST, ${errmsg}" | \
mailx -s "${HOST}: Compile for GTMDefinedTypes.m failed during build of $gtm_verno" $USER
endif
- echo "${errmsg}" >> $gtm_log/error.`basename $gtm_exe`.log
+ echo "${errmsg}" >> $errorlog
endif
# If we have a utf8 dir (created by buildaux.csh called from buildbdp.csh above), add a link to it for
# GTMDefinedTypesInit.m and compile it in UTF8 mode
@@ -734,17 +709,16 @@ if (-e GTMDefinedTypesInit.m) then
setenv gtm_chset UTF-8 # switch to "UTF-8" mode
# mumps executable not yet linked to utf8 dir so access it in parent directory
../mumps GTMDefinedTypesInit.m
- @ savestatus = $status
- if (0 != $savestatus) then
+ if ($status) then
set errmsg = "COMLIST_E-FAIL Failed to compile generated $gtm_exe/utf8/GTMDefinedTypes.m"
if (`expr $gtm_verno \< V900`) then
- @ comlist_status = $savestatus
+ @ comlist_status++
else
echo "Warning: During build of $gtm_verno on $HOST, ${errmsg}" | \
mailx -s "${HOST}: Compile for utf8/GTMDefinedTypes.m failed during build of $gtm_verno" \
$USER
endif
- echo "${errmsg}" >> $gtm_log/error.`basename $gtm_exe`.log
+ echo "${errmsg}" >> $errorlog
endif
popd
setenv LC_CTYPE C
@@ -758,10 +732,15 @@ setenv gtmgbldir ./mumps.gld
gde <<GDE_in1
exit
GDE_in1
-if (0 != $status) @ comlist_status = $status
+
+if ($status) then
+ @ comlist_status++
+ echo "comlist-E-gde, creating $gtmgbldir failed" >> $errorlog
+endif
# Create the GT.M/GDE/MUPIP/DSE/LKE help databases
foreach hlp (*.hlp)
+ set hlp_status = 0
set prefix=${hlp:r}
if ("${prefix}" == "mumps") set prefix="gtm"
setenv gtmgbldir $gtm_dist/${prefix}help.gld
@@ -769,27 +748,26 @@ foreach hlp (*.hlp)
Change -segment DEFAULT -block=2048 -file=\$gtm_dist/${prefix}help.dat
Change -region DEFAULT -record=1020 -key=255
GDE_in_help
- if (0 != $status) @ comlist_status = $status
+ if ($status) @ hlp_status++
mupip create
- if (0 != $status) @ comlist_status = $status
-
+ if ($status) @ hlp_status++
gtm <<GTM_in_gtmhelp
Do ^GTMHLPLD
$gtm_dist/${hlp}
Halt
GTM_in_gtmhelp
- if (0 != $status) @ comlist_status = $status
+
+ if ($status) @ hlp_status++
+ if ($hlp_status) then
+ @ comlist_status = $comlist_status + $hlp_status
+ echo "comlist-E-hlp, Error processing $hlp file" >> $errorlog
+ endif
+
end
chmod 775 * # do not check $status here because we know it will be 1 since "gtmsecshr" permissions cannot be changed.
-# Create the dump file for ZHELP.
-touch $gtm_dist/gtmhelp.dmp
-if (0 != $status) @ comlist_status = $status
-chmod a+rw $gtm_dist/gtmhelp.dmp
-if (0 != $status) @ comlist_status = $status
-
# Create a mirror image (using soft links) of $gtm_dist under $gtm_dist/utf8 if it exists.
if (-e $gtm_exe/utf8) then # would have been created by buildaux.csh while building GDE
pushd $gtm_exe
@@ -806,13 +784,32 @@ if (-e $gtm_exe/utf8) then # would have been created by buildaux.csh while build
# Soft link everything else
if (-e utf8/$file) then
rm -rf utf8/$file
- if (0 != $status) @ comlist_status = $status
+ if ($status) then
+ @ comlist_status++
+ echo "comlist-E-rm, Error deleting utf8/$file" >> $errorlog
+ endif
endif
ln -s ../$file utf8/$file
- if (0 != $status) @ comlist_status = $status
+ if ($status) then
+ @ comlist_status++
+ echo "comlist-E-ln, Error linking $file" >> $errorlog
+ endif
end
popd
endif
+# To check the length of path of files even insdie gtmsecshr directory, relax permissions first
+$gtm_com/IGS $gtm_dist/gtmsecshr UNHIDE
+set distfiles_log = "dist_files.`basename $gtm_exe`.log"
+find $gtm_dist -type f >&! $gtm_log/$distfiles_log
+$gtm_com/IGS $gtm_dist/gtmsecshr CHOWN
+awk 'BEGIN {dlen=length(ENVIRON["gtm_dist"]);stat=0} {if ((length($0)-dlen)>50) {stat=1}} END {exit stat}' $gtm_log/$distfiles_log
+if ($status) then
+ @ comlist_status++
+ echo "comlist-E-pathlength, the longest path beyond \$gtm_dist exceeds 50 bytes" >> $errorlog
+ awk 'BEGIN {dlen=length(ENVIRON["gtm_dist"]);stat=0} \
+ {if ((length($0)-dlen)>50) {print $0,"- length :",length($0)-dlen ; stat=1}} \
+ END {exit stat}' $gtm_log/$distfiles_log >>&! $errorlog
+endif
if ( $comlist_chmod_protect == 1 ) then
# If it is release build, protect it from inadvertent modification/rebuild etc
@@ -824,10 +821,10 @@ comlist.END:
echo ""
echo ""
-if ( -f $gtm_log/error.`basename $gtm_exe`.log ) then
+if ( -f $errorlog ) then
echo "Error summary:"
echo ""
- cat $gtm_log/error.`basename $gtm_exe`.log
+ cat $errorlog
else
echo "No errors were detected by comlist.csh"
endif
diff --git a/sr_unix/comlist.mk b/sr_unix/comlist.mk
deleted file mode 100644
index f01447e..0000000
--- a/sr_unix/comlist.mk
+++ /dev/null
@@ -1,649 +0,0 @@
-#################################################################
-# #
-# Copyright 2001, 2012 Fidelity Information Services, Inc #
-# #
-# This source code contains the intellectual property #
-# of its copyright holder(s), and is made available #
-# under a license. If you do not know the terms of #
-# the license, please stop and do not read further. #
-# #
-#################################################################
-
-# Commands to build GT.M downloaded from SourceForge
-# 1. 'cd' to the GT.M directory where sr_* directories are copied to.
-# 2. Define an environment variable gtm_curpro to point to the full
-# path of the prior GT.M installation.
-# (download and install GT.M binary distribution from SourceForge
-# if you do not have GT.M installed already).
-# 3. To build debug version with no compiler optimzations -
-# gmake -f sr_unix/comlist.mk -I./sr_unix -I./sr_linux buildtypes=dbg gtm_ver=$PWD
-# To build a version enabling optimizations -
-# gmake -f sr_unix/comlist.mk -I./sr_unix -I./sr_linux buildtypes=pro gtm_ver=$PWD
-#
-# By default the build procedure will build 64 bit version of GT.M
-# on a x86_64 machine.
-# If you intend to build 32 bit version of GT.M on a x86_64 bit machine you
-# have to explicitly set the environment variable 'OBJECT_MODE' to '32'
-# Example:
-# OBJECT_MODE=32; export OBJECT_MODE #bourne shell
-# export OBJECT_MODE=32 #bash shell
-# setenv OBJECT_MODE 32 #tcsh shell
-#
-# This procedure requires the tcsh shell to be installed.
-
-# get_lib_dirs.mk must be in the same directory as this makefile
-gt_machine_type=$(shell uname -m)
-gt_os_type=$(shell uname -s)
-
-verbose ?= 0
-# get_lib_dirs.mk defines library directories
-# gt_build_type
-# use_nsb
-# gt_build_xfer_desc
-# it also santizes the CYGWIN gt_os_type
-include get_lib_dirs.mk
-
-CURDIR=$(shell pwd)
-
-ifeq ($(MAKELEVEL),0)
-# the first-level make invocation - rules to create & clean directories
-# and build utilities selectively.
-
-ifndef buildtypes
-buildtypes=pro
-endif
-
-ifndef gtm_ver
-gtm_ver=$(CURDIR)
-endif
-
-ifndef crypttype
-crypttype=gcrypt
-endif
-
-ifeq ($(buildtypes),dbg)
-cryptbuildtype=d
-else
-cryptbuildtype=p
-endif
-
-gt_ar_archiver=ar
-gt_ar_options=rv
-
-# top level make - builds directory structure, calls make for each build type,
-# and creates package
-
-VPATH=$(addprefix $(gtm_ver)/, $(gt_src_list))
-exe_list=mumps dse geteuid lke mupip gtcm_server gtcm_gnp_server gtcm_play gtcm_pkdisp gtcm_shmclean semstat2 ftok dbcertify gtmsecshrdir/gtmsecshr
-make_i_flags=$(addprefix -I$(gtm_ver)/, $(gt_src_list))
-
-export #export all variables defined here to sub-make
-
-# Build the complete suit for packaging - all executables, % utilities,
-# help files etc.
-all: dirs xfer_build gtm_threadgbl_deftypes $(addsuffix _all, $(buildtypes)) ;
-
-# Build xfer_desc.i for ia64 || linux x86_64
-# set in get_lib_dirs.mk
-xfer_build:
-ifeq ($(gt_build_xfer_desc),1)
- tcsh -f $(gtm_ver)/sr_unix/gen_xfer_desc.csh $(gt_src_list)
-endif
-
-gtm_threadgbl_deftypes:
- tcsh -f $(gtm_ver)/sr_unix/gen_gtm_threadgbl_deftypes.csh $(gtm_ver) sr_port $(buildtypes)/obj $(gt_src_list)
-
-dirs: $(addprefix $(gtm_ver)/, $(addsuffix /obj, $(buildtypes))) \
- $(addprefix $(gtm_ver)/, $(addsuffix /map, $(buildtypes))) \
- $(addprefix $(gtm_ver)/, $(addsuffix /plugin, $(buildtypes))) ;
-
-# Compile and archive all modules and stop.
-compile: dirs $(addsuffix _compile, $(buildtypes)) ;
-
-# Build all executables and stop.
-links: dirs $(addsuffix _links, $(buildtypes)) ;
-
-# Rules to make executables selectively (eg. make mumps, make dse etc..)
-$(exe_list):%: dirs $(addsuffix _%, $(buildtypes)) ;
-
-setperms:
-ifeq ($(shell id -u),0)
- @chown root:bin ${buildtypes}/gtmsecshr ${buildtypes}/gtmsecshrdir/gtmsecshr
- @chmod 4750 ${buildtypes}/gtmsecshr ${buildtypes}/gtmsecshrdir/gtmsecshr
-else
- @echo "Operation requires super user capabilities"
-endif
-
-clean: $(addsuffix _clean, $(buildtypes))
- rm -f idtemp ostemp
-
-# Package GT.M installation kit.
-package: $(addsuffix _tar, $(buildtypes))
-
-%_tar: release_name.h
- @echo "packaging GT.M..."
- grep RELEASE_NAME $< | awk '{print $$4}' | sed 's/[\.]//' | sed 's/-//' > idtemp
-ifeq ($(MACHTYPE),x86_64)
-# On a 64 bit machine switch between 64 bit and 32 bit depending upon
-# the OBJECT_MODE environment variable
-ifeq ($(gt_build_type),64)
- @tar -zcvf gtm_`head -n 1 idtemp`_$(OSTYPE)_$(MACHTYPE)_$*.tar.gz -C $* $(filter-out obj map, $(notdir $(wildcard $*/*)))
-else
- @tar -zcvf gtm_`head -n 1 idtemp`_$(OSTYPE)_i686_$*.tar.gz -C $* $(filter-out obj map, $(notdir $(wildcard $*/*)))
-endif
-else
-
-ifeq ($(OSTYPE),hpux)
-# IA64 HP-UX has MACHTYPE set to unknown; so use uname -m
-# tar doesnt support "z" (to zip) option; so needs a separate gzip command
-ifeq ($(gt_machine_type), ia64)
- @tar -cvf gtm_`head -n 1 idtemp`_$(OSTYPE)_$(gt_machine_type)_$*.tar -C $* $(filter-out obj map, $(notdir $(wildcard $*/*)))
- @gzip gtm_`head -n 1 idtemp`_$(OSTYPE)_$(gt_machine_type)_$*.tar
-else
- @tar -cvf gtm_`head -n 1 idtemp`_$(OSTYPE)_`echo $(MACHTYPE) | sed 's/_//1'`_$*.tar -C $* $(filter-out obj map, $(notdir $(wildcard $*/*)))
- @gzip gtm_`head -n 1 idtemp`_$(OSTYPE)_`echo $(MACHTYPE) | sed 's/_//1'`_$*.tar
-endif
-
-else
- @tar -zcvf gtm_`head -n 1 idtemp`_$(OSTYPE)_$(MACHTYPE)_$*.tar.gz -C $* $(filter-out obj map, $(notdir $(wildcard $*/*)))
-endif
-endif
- rm -f idtemp
-
-%_clean:
- rm -rf $(gtm_ver)/$*
- rm -f $(gtm_ver)/*$*.tar.gz
-%/obj:
- mkdir -p $@
-%/map:
- mkdir -p $@
-%/plugin:
- mkdir -p $@/gtmcrypt
-
-dbg_%:comlist.mk
- $(MAKE) -C $(gtm_ver)/dbg/obj -I$(gtm_ver)/dbg/obj $(make_i_flags) -f $< CURRENT_BUILDTYPE=dbg $*
-pro_%:comlist.mk
- $(MAKE) -C $(gtm_ver)/pro/obj -I$(gtm_ver)/pro/obj $(make_i_flags) -f $< CURRENT_BUILDTYPE=pro $*
-bta_%:comlist.mk
- $(MAKE) -C $(gtm_ver)/bta/obj -I$(gtm_ver)/bta/obj $(make_i_flags) -f $< CURRENT_BUILDTYPE=bta $*
-
-else
-# Second-level make invocation: compute dependencies, compile, archive,
-# link and test.
-
-# gt_src_list is the list of all source (sr_*) directories. allfiles_list
-# is the superset of all GT.M files (.c, .s, .m, .list, etc. etc.) present
-# in all sr_* directories. ttt.c is generated from ttt.txt
-allfiles_list:=$(sort $(notdir $(foreach d,$(gt_src_list),$(wildcard $(gtm_ver)/$(d)/*))) ttt.c)
-
-# allfiles_list computation should precede this include, since
-# os390:gtm_env_sp.mk requires $(allfiles_list)
-include gtm_env_sp.mk
-
-# the list of all GT.M executables
-exe_list:=libgtmshr$(gt_ld_shl_suffix) $(exe_list) $(gt_svc_exe)
-
-
-# In the following code, various categories of source files are filtered
-# from allfiles_list into separate variables based on the file extention.
-
-# m file stuff. These list builds go to great pain to insure that either
-# post cms_load forms and pre-cms load forms work.
-plugin_cfiles:= gtmcrypt_ref.c gtmcrypt_pk_ref.c gtmcrypt_dbk_ref.c maskpass.c
-plugin_hfiles:= gtmcrypt_ref.h gtmcrypt_pk_ref.h gtmcrypt_dbk_ref.h gtmcrypt_sym_ref.h gtmcrypt_interface.h
-plugin_sh_file:= build.sh install.sh add_db_key.sh encrypt_sign_db_key.sh gen_keypair.sh gen_sym_hash.sh gen_sym_key.sh import_and_sign_key.sh pinentry-gtm.sh
-plugin_mfile:=pinentry.m
-mfile_list:=$(filter-out _%.m, $(filter %.m, $(allfiles_list)))
-mptfile_list:=$(sort $(basename $(filter %.mpt, $(allfiles_list))) $(basename $(patsubst _%.m, %, $(filter _%.m, $(allfiles_list)))))
-mfile_targets:=$(addsuffix .m,$(foreach f,$(basename $(mfile_list)), $(shell echo $(f) | tr '[:lower:]' '[:upper:]')))
-mptfile_targets:=$(addprefix _,$(addsuffix .m, $(foreach f,$(mptfile_list), $(shell echo $(f) | tr '[:lower:]' '[:upper:]'))))
-cfile_list:=$(filter-out $(plugin_cfiles), $(filter %.c, $(allfiles_list)))
-ifdef gt_as_src_from_suffix
-#
-# DUX requires .m64 to be gawk'ed and assembled as well
-#
-sfile_list:=$(filter %$(gt_as_src_suffix) %$(gt_as_src_from_suffix), $(allfiles_list))
-else
-sfile_list:=$(filter %$(gt_as_src_suffix), $(allfiles_list))
-endif
-
-helpfile_list:=$(filter %.hlp, $(allfiles_list))
-sh_list:=$(filter %.sh, $(allfiles_list))
-gtc_list:=$(filter %.gtc, $(allfiles_list))
-list_files:=$(filter %.list, $(allfiles_list))
-msgfile_list:=$(filter %.msg, $(allfiles_list))
-plugin_ksh_file:=$(filter %.ksh, $(allfiles_list))
-
-hfile_list := gtm_stdio.h gtm_stdlib.h gtm_string.h gtm_strings.h gtmxc_types.h gtm_limits.h gtm_common_defs.h \
- main_pragma.h $(hfile_list_sp)
-sh_targets:=$(basename $(sh_list))
-
-msgcfile_list=$(addsuffix _ctl.c,$(basename $(msgfile_list)))
-msgofile_list=$(addsuffix .o,$(basename $(msgcfile_list)))
-list_file_libs=$(addsuffix .a,$(basename $(list_files)))
-
-
-# object files
-# NOTE: sort/basename weeds out .s, .c duplication and
-# rules giving %.s priority over %.c cause the %.s
-# version to always be used
-ofile_list:=$(addsuffix .o,$(sort $(basename $(cfile_list)) $(basename $(sfile_list))))
-
-#
-# dynamic depend list - weed out .s based .o's
-#
-dep_list:=$(addsuffix .d,$(filter-out $(basename $(sfile_list)),$(basename $(cfile_list))))
-
-# objects on link command lines
-mumps_obj=gtm.o
-gtmshr_obj=gtm_main.o
-lke_obj=lke.o lke_cmd.o
-dse_obj=dse.o dse_cmd.o
-mupip_obj=mupip.o mupip_cmd.o
-dbcertify_obj=dbcertify.o dbcertify_cmd.o
-gtmsecshr_obj=gtmsecshr.o
-gtmsecshr_wrapper_obj=gtmsecshr_wrapper.o
-geteuid_obj=geteuid.o
-semstat2_obj=semstat2.o
-ftok_obj=ftok.o
-gtcm_server_obj=gtcm_main.o omi_srvc_xct.o
-gtcm_gnp_server_obj=gtcm_gnp_server.o
-gtcm_play_obj=gtcm_play.o omi_sx_play.o
-gtcm_pkdisp_obj=gtcm_pkdisp.o
-gtcm_shmclean_obj=gtcm_shmclean.o
-dtgbldir_obj=dtgbldir.o
-dummy_gtmci_obj=dummy_gtmci.o
-
-# exclude .o's in .list files, .o's used in ld's below, plus dtgbldir.o
-# (which doesn't appear to be used anywhere!
-non_mumps_objs:=$(addsuffix .o,$(shell cat $(foreach d,$(gt_src_list),$(wildcard $(gtm_ver)/$(d)/*.list))))
-exclude_list:= \
- $(non_mumps_objs) \
- $(mumps_obj) \
- $(gtmshr_obj) \
- $(gtm_svc_obj) \
- $(lke_obj) \
- $(dse_obj) \
- $(mupip_obj) \
- $(dbcertify_obj) \
- $(gtmsecshr_obj) \
- $(gtmsecshr_wrapper_obj) \
- $(geteuid_obj) \
- $(semstat2_obj) \
- $(ftok_obj) \
- $(gtcm_server_obj) \
- $(gtcm_gnp_server_obj) \
- $(gtcm_play_obj) \
- $(gtcm_pkdisp_obj) \
- $(gtcm_shmclean_obj) \
- $(dtgbldir_obj) \
- $(dummy_gtmci_obj)
-
-# retain_list contains the modules listed in a .list file that also need to be
-# included in libmumps.a (eg. getmaxfds, sleep in sr_sun:libgtmrpc.list)
-libmumps_obj:=$(sort $(filter-out $(exclude_list),$(ofile_list)) $(msgofile_list) $(retain_list))
-
-# rules, lists, variables specific to each type of build
-
-#ifndef gtm_dist
-gtm_dist=$(gtm_ver)/$(CURRENT_BUILDTYPE)
-#endif
-
-gt_cc_option_I:=$(gt_cc_option_I) $(addprefix -I$(gtm_ver)/, $(gt_src_list)) -I$(CURDIR)
-gt_cc_option_DDEBUG=-DDEBUG
-ifeq ($(CURRENT_BUILDTYPE), pro)
-gt_cc_options=$(gt_cc_option_optimize) $(gt_cc_options_common)
-gt_as_options=$(gt_as_option_optimize) $(gt_as_options_common)
-gt_ld_options_buildsp=$(gt_ld_options_pro)
-endif
-ifeq ($(CURRENT_BUILDTYPE), bta)
-gt_cc_options=$(gt_cc_option_DDEBUG) $(gt_cc_option_optimize) $(gt_cc_options_common)
-gt_as_options=$(gt_as_option_DDEBUG) $(gt_as_option_optimize) $(gt_as_options_common)
-gt_ld_options_buildsp=$(gt_ld_options_bta)
-endif
-ifeq ($(CURRENT_BUILDTYPE), dbg)
-gt_cc_options=$(gt_cc_option_DDEBUG) $(gt_cc_option_debug) $(gt_cc_options_common)
-gt_as_options=$(gt_as_option_DDEBUG) $(gt_as_option_debug) $(gt_as_options_common)
-gt_ld_options_buildsp=$(gt_ld_options_dbg)
-endif
-gt_cc_options += $(gt_cc_option_I)
-gt_as_options += $(gt_cc_option_I)
-
-# gt_ld_options should be set with '=' to allow lazy evaluation of
-# gt_ld_options_loadmap
-gt_ld_options=$(gt_ld_options_common) $(gt_ld_options_buildsp) $(gt_ld_options_loadmap) -L$(CURDIR)
-
-gt_cpus ?= 2
-
-ifdef gt_ar_gtmrpc_name
-gt_ar_gtmrpc_name_target=../lib$(gt_ar_gtmrpc_name).a
-endif
-
-postbuild=$(gt_ar_gtmrpc_name_target) dotsh helpfiles hfiles gtcmconfig cpplugin_scripts cpplugin_file cpplugin_mfile\
- ../mumps.gld ../gtmhelp.dat ../gdehelp.dat build_plugin_lib
-
-all: links mfiles mcompiles testit $(postbuild)
-
-compile:libmumps.a $(list_file_libs) $(filter-out $(non_mumps_objs), $(exclude_list))
-
-%.export:%.exp
- $(gt-export)
-
-testit:
- echo $(postbuild)
-
-links: $(exe_list)
-$(exe_list):%: $(prebuild) ../% ;
-
-vars:
- echo MAKECMDGOALS $(MAKECMDGOALS)
-
-../mumps.gld:
- cd ..;gtm_dist=$(gtm_dist);export gtm_dist;gtmgbldir=./$(notdir $@);export gtmgbldir;\
- echo exit | ./mumps -run GDE
-
-define compile-help
-cd ..;gtm_dist=$(gtm_dist);export gtm_dist;gtmgbldir=$(gtm_dist)/$(notdir $(basename $@));export gtmgbldir; \
- echo Change -segment DEFAULT -block=2048 -file=$(gtm_dist)/$(notdir $@) > hctemp; \
- echo Change -region DEFAULT -record=1020 -key=255 >> hctemp; \
- echo exit >> hctemp; \
- cat hctemp | ./mumps -run GDE; \
- ./mupip create; \
- echo "Do ^GTMHLPLD" > hctemp; \
- echo $(gtm_dist)/$(notdir $^) >> hctemp; \
- echo Halt >> hctemp; \
- cat hctemp | ./mumps -direct; \
- rm -f hctemp
-endef
-../gtmhelp.dat: ../mumps.hlp
- $(compile-help)
-../gdehelp.dat: ../gde.hlp
- $(compile-help)
-
-mcompiles:
- cd ..;gtm_dist=$(dir $(CURDIR));export gtm_dist;gtmgbldir=$(notdir $@);export gtmgbldir; LC_CTYPE=C; export LC_CTYPE; gtm_chset=M; export gtm_chset; ./mumps *.m ; tcsh -f ../sr_unix/mkutf8dir.csh
-
-pluginbuild:
- mkdir -p plugin/gtmcrypt; cp ../sr_unix/gtmcrypt_ref.h plugin/gtmcrypt/; cp ../sr_unix/gtmcrypt_ref.c plugin/gtmcrypt/;
-
-dotsh: $(sh_targets)
- cp -f $^ ..
-
-helpfiles: $(helpfile_list)
- cp -pf $^ ..
-
-hfiles: $(hfile_list)
- cp -f $^ ..
-ifeq ($(gt_os_type), OSF1)
-cpplugin_scripts: $(plugin_ksh_file) $(plugin_sh_file)
-
-cpplugin_file: $(plugin_cfiles) $(plugin_hfiles)
-
-cpplugin_mfile: $(plugin_mfile)
-
-build_plugin_lib:
-else
-cpplugin_scripts: $(plugin_ksh_file) $(plugin_sh_file)
- cp -f $^ ../plugin/gtmcrypt
-cpplugin_file: $(plugin_cfiles) $(plugin_hfiles)
- cp -f $^ ../plugin/gtmcrypt
-cpplugin_mfile: $(plugin_mfile)
- cp -f $^ ../plugin/gtmcrypt/
-build_plugin_lib:
- gtm_dist=$(dir $(CURDIR));export gtm_dist;cd $(gtm_dist)/plugin/gtmcrypt;sh -f build.sh $(crypttype) $(cryptbuildtype); sh -f install.sh
-endif
-
-mfiles: $(addprefix ../, $(mfile_targets) $(mptfile_targets))
-
-$(list_file_libs): $(list_files)
-
-ifdef gt_ar_gtmrpc_name_target
-$(gt_ar_gtmrpc_name_target): lib$(gt_ar_gtmrpc_name).a
- cp $< $@
-endif
-
-# executables
-define gt-ld
-rm -f $@
- at echo "linking $(notdir $@)..."
- at echo $(gt_ld_linker) $(gt_ld_options) -o $@ $(gt_ld_sysrtns) $+ $(gt_ld_syslibs) $(gt_ld_extra_libs) > ../map/$(notdir $@).map 2>&1
-@$(gt_ld_linker) $(gt_ld_options) -o $@ $(gt_ld_sysrtns) $+ $(gt_ld_syslibs) $(gt_ld_extra_libs) >> ../map/$(notdir $@).map 2>&1
-endef
-define gt-ld_with_export
-rm -f $@
- at echo "linking $(notdir $@)..."
- at echo $(gt_ld_linker) $(gt_ld_options) -o $@ $(gt_ld_sysrtns) $(gt_ld_options_all_exe) $+ $(gt_ld_syslibs) $(gt_ld_extra_libs) > ../map/$(notdir $@).map 2>&1
-@$(gt_ld_linker) $(gt_ld_options) -o $@ $(gt_ld_sysrtns) $(gt_ld_options_all_exe) $+ $(gt_ld_syslibs) $(gt_ld_extra_libs) >> ../map/$(notdir $@).map 2>&1
-endef
-
-ifdef gt_svc_exe
-# Note: gtm_svc should link with gtm_dal_svc.o before
-# gtm_mumps_call_clnt.o(libgtmrpc.a) to resolve conflicting symbols
-# (gtm_init_1, gtm_halt_1 etc..) appropriately.
-../$(gt_svc_exe): $(gtm_svc_obj) libmumps.a libgnpclient.a libcmisockettcp.a $(gt_ld_gtmrpc_library_option)
- $(gt-ld)
-endif
-
-../mumps: $(mumps_obj)
- $(gt-ld)
-
-../dse: $(dse_obj) libdse.a libmumps.a libstub.a
- $(gt-ld_with_export)
-
-../geteuid: $(geteuid_obj) libmumps.a
- $(gt-ld)
-
-../gtmsecshrdir/gtmsecshr: ../gtmsecshr_real ../gtmsecshr_wrapper
- @rm -rf ../gtmsecshrdir gtmsecshr && mkdir ../gtmsecshrdir
- @mv ../gtmsecshr_real ../gtmsecshrdir/gtmsecshr
- @mv ../gtmsecshr_wrapper ../gtmsecshr
-
-../gtmsecshr_real: $(gtmsecshr_obj) libmumps.a
- $(gt-ld)
-
-../gtmsecshr_wrapper: $(gtmsecshr_wrapper_obj) libmumps.a
- $(gt-ld)
-
-../lke: $(lke_obj) liblke.a libmumps.a libgnpclient.a libmumps.a libgnpclient.a libcmisockettcp.a
- $(gt-ld)
-
-../mupip: $(mupip_obj) libmupip.a libmumps.a libstub.a $(gt_ld_aio_syslib)
- $(gt-ld_with_export)
-
-../dbcertify: $(dbcertify_obj) libdbcertify.a libmupip.a libmumps.a libstub.a $(gt_ld_aio_syslib)
- $(gt-ld)
-
-../gtcm_server: $(gtcm_server_obj) libgtcm.a libmumps.a libstub.a
- $(gt-ld)
-
-../gtcm_gnp_server: $(gtcm_gnp_server_obj) libgnpserver.a liblke.a libmumps.a libcmisockettcp.a libstub.a
- $(gt-ld)
-
-../gtcm_play: $(gtcm_play_obj) libgtcm.a libmumps.a libstub.a
- $(gt-ld)
-
-../gtcm_pkdisp: $(gtcm_pkdisp_obj) libgtcm.a libmumps.a libstub.a
- $(gt-ld)
-
-../gtcm_shmclean: $(gtcm_shmclean_obj) libgtcm.a libmumps.a libstub.a
- $(gt-ld)
-
-../semstat2: $(semstat2_obj)
- $(gt-ld)
-
-../ftok: $(ftok_obj) libmumps.a
- $(gt-ld)
-
-# build GT.M shared library(libgtmshr) from PIC-compiled .o files
-# chcon is for SELinux - see comment in buildshr.csh
-../libgtmshr$(gt_ld_shl_suffix): gtmshr_symbols.export gtmexe_symbols.export $(gtmshr_obj) libmumps.a libgnpclient.a libcmisockettcp.a
- rm -f $@
- @echo "linking $(notdir $@)..."
- @echo $(gt_ld_linker) $(gt_ld_options) $(gt_ld_shl_options) $(gt_ld_options_gtmshr) -o $@ $(gtmshr_obj) -lmumps -lgnpclient -lcmisockettcp $(gt_ld_syslibs) > ../map/$(notdir $@).map 2>&1
- @$(gt_ld_linker) $(gt_ld_options) $(gt_ld_shl_options) $(gt_ld_options_gtmshr) -o $@ $(gtmshr_obj) -lmumps -lgnpclient -lcmisockettcp $(gt_ld_syslibs) >> ../map/$(notdir $@).map 2>&1
-ifeq ($(gt_os_type),Linux)
- @-[ -x /usr/bin/chcon ] && chcon -t texrel_shlib_t $@
-endif
-
-gtcmconfig: $(gtc_list)
- cp -f $^ ..
- cd ..;chmod a-wx $(notdir $^);mv -f configure.gtc configure
- cd ..;touch gtmhelp.dmp;chmod a+rw gtmhelp.dmp
-
-test_type:
-ifndef gt_cc_options
- $(error CURRENT_BUILDTYPE not properly defined)
-endif
-
-# no need to keep the archived object files
-.INTERMEDIATE: $(libmumps_obj) $(non_mumps_objs)
-
-#
-# autodepend files for C files
-#
--include $(dep_list)
-#
-# autodepend files for M files
-#
--include $(mfile_list:.m=.mdep)
-#
-# autodepend files for mpt files
-#
--include $(mptfile_list:=.mptdep)
-#
-# autodepend files for .a files
-#
--include $(list_files:.list=.ldep)
-
-# Overriding the implicit archive rule a(m):m to accumulate all changed .o
-# files in a temporary dependency (.ardep) file that will be used by ar to
-# archive all files in a single command.
-# This enhancement [of accumulating in a temporary .ardep file instead of
-# updating the library rightaway] improves the full building time. However
-# for incremental builds the object file is updated into the archive
-# immediately.
-(%):%
-ifeq ($(incremental),1)
- @$(gt_ar_archiver) $(gt_ar_options) $@ $<
-else
- @echo $< >> $(basename $@).ardep
-endif
-
-# Since ecode_set.c includes merrors_ansi.h, merrors.msg should be precompiled.
-ecode_set.d:merrors_ctl.c
-
-%.d:%.c
-ifeq ($(verbose),1)
- @echo generating $@...
-endif
- $(gt-dep)
-
-ifeq ($(incremental),1)
-%.ldep:%.list
- @echo $*.a\:$*.a\($$\(addsuffix .o,$$\(shell cat $<\)\)\) > $@
- @$(gt_echoe) "\t at ranlib "$$\@ >> $@
-else
-%.ldep:%.list
- @echo $*.a\:$*.a\($$\(addsuffix .o,$$\(shell cat $<\)\)\) $*.ardep > $@
- @$(gt_echoe) "\t at echo Processing "$$\@ "; cp -f $*.ardep _$*.ardep; echo >$*.ardep" >> $@
- @$(gt_echoe) "\t at cat _$*.ardep | xargs $(gt_ar_archiver) $(gt_ar_options) "$$\@ >>$@
- @$(gt_echoe) "\t at rm -f _$*.ardep" >> $@
-endif
-
-%.mdep:%.m
- @echo ../$(shell echo $* | tr '[:lower:]' '[:upper:]').m: $< > $@
- @$(gt_echoe) "\t"cp -f $$\< $$\@ >> $@
-%.mptdep:_%.m
- @echo ../_$(shell echo $* | tr '[:lower:]' '[:upper:]').m: $< > $@
- @$(gt_echoe) "\t"cp -f $$\< $$\@ >> $@
-%.mptdep:%.mpt
- @echo ../_$(shell echo $* | tr '[:lower:]' '[:upper:]').m: $< > $@
- @$(gt_echoe) "\t"cp -f $$\< $$\@ >> $@
-
-# By setting gtm_curpro to point to a prior installed GT.M directory (if
-# available), the following rules automatically generates *_ctl.c from *.msg
-# and ttt.c from ttt.txt.
-ifdef gtm_curpro
-%_ctl.c:%.msg msg.m
- gtm_dist=$(gtm_curpro);export gtm_dist;\
- $(gtm_curpro)/mumps $(filter-out $<, $^);\
- $(gtm_curpro)/mumps -run msg $< unix
- @rm -f msg.o
-
-ttt.c:ttt.txt opcode_def.h vxi.h tttgen.m tttscan.m chk2lev.m chkop.m gendash.m genout.m loadop.m loadvx.m
- gtm_dist=$(gtm_curpro);export gtm_dist;\
- $(gtm_curpro)/mumps $(filter-out %.h, $(filter-out $<, $^));\
- $(gtm_curpro)/mumps -run tttgen $< $(filter %.h, $^)
- @rm -f tttgen.o tttscan.o chk2lev.o chkop.o gendash.o genout.o loadop.o loadvx.o
-endif
-
-# By default [since the rule %.o:%.s precedes %.o:%.c], the .s files take
-# precedence over .c files if both versions exist for a module. The
-# following rule allows us to reverse this behavior for a special set of
-# modules (eg. compswap for sparcv8 etc.) by assigning them to a variable
-# gt_cc_before_as [in gtm_env_sp.mk].
-# gt_cc_before_as should be defined to the list of .o files for which both
-# .c and .s exist but need to be compiled from .c instead of from .s files.
-ifdef gt_cc_before_as
-$(gt_cc_before_as):%.o:%.c #override rules for gt_cc_before_as modules ONLY
-ifeq ($(verbose),1)
- $(gt_cc_compiler) -c $(gt_cc_options) -o $@ $<
-else
- @echo "$< ----> $(CURDIR)/$@"
- @$(gt_cc_compiler) -c $(gt_cc_options) -o $@ $<
-endif
-endif
-
-ifdef gt_as_src_from_suffix
-%.o:%$(gt_as_src_from_suffix)
-ifeq ($(verbose),1)
- $(gt-as-convert)
-else
- @echo "$< ----> $(CURDIR)/$@"
- @$(gt-as-convert)
-endif
-endif
-
-%.o:%$(gt_as_src_suffix)
-ifneq ($(verbose),1)
- @echo "$< ----> $(CURDIR)/$@"
-endif
-ifeq ($(gt_os_type), Linux)
-ifeq ($(gt_machine_type), ia64)
- @$(gt_cpp)
- @$(gt-as_cpp)
- @rm $<_cpp.s
-else
- @$(gt-as)
-endif
-else
-ifeq ($(gt_os_type)), CYGWIN)
- @$(gt-as)
- objcopy --prefix-symbols="_" $@
-else
- @$(gt-as)
-endif
-endif
-
-%.o:%.c
-ifeq ($(verbose),1)
- $(gt_cc_compiler) -c $(gt_cc_options) -o $@ $<
-else
- @echo "$< ----> $(CURDIR)/$@"
- @$(gt_cc_compiler) -c $(gt_cc_options) -o $@ $<
-endif
-
-omi_sx_play.c: omi_srvc_xct.c
- @cp $< $@
-
-ifeq ($(incremental),1)
-libmumps.a: libmumps.a($(msgofile_list) $(libmumps_obj))
- @ranlib $@
-else
-libmumps.a: libmumps.a($(msgofile_list) $(libmumps_obj)) libmumps.ardep
- @echo Processing $@ ;cp -f libmumps.ardep _libmumps.ardep; echo "">libmumps.ardep
- @cat _libmumps.ardep | xargs $(gt_ar_archiver) $(gt_ar_options) $@
- @rm -f _libmumps.ardep
-endif
-
-endif #second-level make invocation
diff --git a/sr_unix/configure.gtc b/sr_unix/configure.gtc
index f79f876..415eaa0 100644
--- a/sr_unix/configure.gtc
+++ b/sr_unix/configure.gtc
@@ -1,7 +1,7 @@
#!/bin/sh
#################################################################
# #
-# Copyright 2009, 2013 Fidelity Information Services, Inc #
+# Copyright 2009, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -95,16 +95,10 @@ if [ $deliver_gtcm_gnp = "yes" ]; then
binaries="$binaries gtcm_gnp_server"
fi
-# Other files
+# Help files
hlpfiles="*help.dat *help.gld *.h"
-if [ $arch = "sco" ]; then
- ofiles="$hlpfiles esnecil"
-elif [ $arch = "sun" -o $arch = "solaris" ]; then
- ofiles="$hlpfiles libgtmrpc.a"
- binaries="$binaries gtm_svc"
-else
- ofiles="$hlpfiles"
-fi
+# Other files (left here for future use)
+ofiles="$hlpfiles"
# Files that need to have $gtm_dist, $echo, etc. set in them.
pathmods="gtmbase.gtc gtmstart.gtc gtmstop.gtc gtmcshrc.gtc gtmprofile.gtc gtm.gtc gtmprofile_preV54000.gtc gdedefaults.gtc"
@@ -122,7 +116,7 @@ if [ "`./geteuid`" != "root" ] ; then
fi
$echo " GT.M Configuration Script"
-$echo "Copyright 2009, 2013 Fidelity Information Services, Inc. Use of this"
+$echo "Copyright 2009, 2014 Fidelity Information Services, Inc. Use of this"
$echo "software is restricted by the provisions of your license agreement."
$echo ""
@@ -186,6 +180,10 @@ if [ `$echo $gtmdist | grep -c '^/'` -eq 0 ] ; then
gtmdist=`pwd`/$gtmdist
fi
+# ensure that canonical paths do not exceed PATH_MAX
+getconf PATH_MAX $gtmdist | \
+ awk '{max=$0-max;if(max<0)max+=1024;if(length(dist)>max){print dist" exceeds the maximum path length: "max;exit 1}}' \
+ dist=$gtmdist max=50 || exit
$echo ""
if [ -d $gtmdist ]; then
@@ -367,16 +365,23 @@ else
doutf8=0
fi
-#if gdedefaults exists on z/OS then remove it so tagging will occur correctly
+# If gdedefaults exists on z/OS then remove it so tagging will occur correctly
if [ $arch = "zos" -a -f gdedefaults ] ; then
rm gdedefaults
fi
+
+# Solaris 10 bourne shell does not support ${var#word} syntax
+install_dest=$gtmdist
+if [ X"$gtm_destdir" != X"" ] ; then
+ install_dest=`echo $install_dest | sed "s;${gtm_destdir};;"`
+fi
+
# Modify the scripts as necessary for target configuration
cat << SEDSCRIPT > sedin$$
s|ARCH|$arch|g
s|ECHO|"$echo"|g
-s|GTMDIST|$gtmdist|g
+s|GTMDIST|${install_dest}|g
s|SERVERID|$server_id|g
SEDSCRIPT
for i in $pathmods
@@ -391,7 +396,7 @@ do
fi
done
rm sedin$$
-#on z/OS gdedefaults must be tagged ascii to be used by GTM.
+# On z/OS gdedefaults must be tagged ascii to be used by GTM.
if [ $arch = "zos" ]; then
iconv -T -f IBM-1047 -t ISO8859-1 gdedefaults > t.gdedefaults
mv t.gdedefaults gdedefaults
@@ -402,7 +407,7 @@ if [ "$doutf8" -ne 0 ]; then
fi
fi
-# copy debug files if necessary
+# Copy debug files if necessary
if [ $arch = "zos" ] ; then
for i in `ls *.mdbg 2> /dev/null` ; do
cp -p $i $gtmdist
@@ -490,9 +495,6 @@ do
cp -p $i $gtmdist
chown $owner $gtmdist/$i
done
-if [ $arch = "sun" ]; then
- ranlib -t $gtmdist/libgtmrpc.a
-fi
# For linux systems, attempt to execute the chcon command to allow use of the libgtmshr shared library. This
# command is required on many modern SELinux based systems but depends on the filesystem in use (requires context
@@ -519,7 +521,7 @@ gtmcryptsharedlibs="$gtmcryptsharedlibs libgtmcrypt_gcrypt_AES256CFB$ext libgtmc
gtmcryptsharedlibs="$gtmcryptsharedlibs libgtmtls$ext libgtmcryptutil$ext"
# Gtmcrypt scripts
-gtmcryptscripts="add_db_key.sh gen_sym_key.sh encrypt_sign_db_key.sh gen_keypair.sh pinentry-gtm.sh"
+gtmcryptscripts="gen_sym_key.sh encrypt_sign_db_key.sh gen_keypair.sh pinentry-gtm.sh"
gtmcryptscripts="$gtmcryptscripts import_and_sign_key.sh gen_sym_hash.sh show_install_config.sh"
# Gtmcrypt related M file
@@ -609,7 +611,7 @@ if [ -d "$plugin_gtmcrypt" ]; then
# Install gpgagent.tab
# This is an external call table so the path to the shared library has to be adjusted
- echo "$gtmdist/plugin/libgtmcryptutil$ext" > $gtmdist/$plugin/gpgagent.tab
+ echo "${install_dest}/plugin/libgtmcryptutil$ext" > $gtmdist/$plugin/gpgagent.tab
cat $plugin/gpgagent.tab | sed 1d >> $gtmdist/$plugin/gpgagent.tab
# Tar the source files
@@ -804,7 +806,7 @@ if [ -f $gtm_dist/libgtmutil$ext ] ; then
$echo "Object files of M routines placed in shared library $gtm_dist/libgtmutil$ext"
$echo "Keep original .o object files (y or n)? \c"
read resp
- if [ "n" = $resp -o "N" = $resp ] ; then rm -f $gtm_dist/*.o $gtm_dist/utf8/*.o ; fi
+ if [ "n" = "$resp" -o "N" = "$resp" ] ; then rm -f $gtm_dist/*.o $gtm_dist/utf8/*.o ; fi
$echo ""
if [ -f $gtm_dist/utf8/libgtmutil$ext ] ; then
chown ${owner}:${bingroup} $gtm_dist/utf8/libgtmutil$ext
@@ -919,7 +921,7 @@ read resp
if [ "$resp" = "Y" -o "$resp" = "y" ] ; then
\rm -rf $binaries $pathmods $rscripts $nscripts $dirs configure \
*.gtc gtm* gde* GDE*.o _*.m _*.o mumps.dat mumps.gld geteuid $other_object_files $csh_script_files lowerc_cp\
- esnecil *.hlp core *.h libgtmrpc.a *.m *help.dat *help.gld COPYING README.txt
+ *.hlp core *.h *.m *help.dat *help.gld COPYING README.txt
\rm -rf GETPASS.o plugin PINENTRY.o GTMHELP.o custom_errors_sample.txt
if [ -d utf8 ]; then
\rm -rf utf8
diff --git a/sr_unix/ctrlc_set.c b/sr_unix/ctrlc_set.c
index bccb071..1fa6602 100644
--- a/sr_unix/ctrlc_set.c
+++ b/sr_unix/ctrlc_set.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,24 +24,21 @@
* Note: dummy parameter is for calling compatibility.
* ------------------------------------------------------------------
*/
-GBLREF xfer_entry_t xfer_table[];
-GBLREF volatile bool ctrlc_on;
+GBLREF volatile boolean_t ctrlc_on;
GBLREF volatile int4 ctrap_action_is, outofband;
+GBLREF xfer_entry_t xfer_table[];
void ctrlc_set(int4 dummy_param)
{
- if (!outofband && IS_MCODE_RUNNING)
+ if (!outofband && IS_MCODE_RUNNING && ctrlc_on)
{
- if (ctrlc_on)
- {
- ctrap_action_is = 0;
- outofband = ctrlc;
- FIX_XFER_ENTRY(xf_linefetch, op_fetchintrrpt);
- FIX_XFER_ENTRY(xf_linestart, op_startintrrpt);
- FIX_XFER_ENTRY(xf_zbfetch, op_fetchintrrpt);
- FIX_XFER_ENTRY(xf_zbstart, op_startintrrpt);
- FIX_XFER_ENTRY(xf_forchk1, op_startintrrpt);
- FIX_XFER_ENTRY(xf_forloop, op_forintrrpt);
- }
+ ctrap_action_is = 0;
+ outofband = ctrlc;
+ FIX_XFER_ENTRY(xf_linefetch, op_fetchintrrpt);
+ FIX_XFER_ENTRY(xf_linestart, op_startintrrpt);
+ FIX_XFER_ENTRY(xf_zbfetch, op_fetchintrrpt);
+ FIX_XFER_ENTRY(xf_zbstart, op_startintrrpt);
+ FIX_XFER_ENTRY(xf_forchk1, op_startintrrpt);
+ FIX_XFER_ENTRY(xf_forloop, op_forintrrpt);
}
}
diff --git a/sr_unix/custom_errors_sample.txt b/sr_unix/custom_errors_sample.txt
index b289103..2d1fa36 100644
--- a/sr_unix/custom_errors_sample.txt
+++ b/sr_unix/custom_errors_sample.txt
@@ -24,6 +24,7 @@ JNLFILEXTERR
JNLFILOPN
JNLFLUSH
JNLFSYNCERR
+JNLOPNERR
JNLRDERR
JNLREAD
JNLVSIZE
diff --git a/sr_unix/db_ipcs_reset.c b/sr_unix/db_ipcs_reset.c
index d341e30..700199c 100644
--- a/sr_unix/db_ipcs_reset.c
+++ b/sr_unix/db_ipcs_reset.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -92,17 +92,17 @@ boolean_t db_ipcs_reset(gd_region *reg)
gv_cur_region = temp_region;
if (SS_NORMAL != status)
{
- gtm_putmsg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
return FALSE;
}
LSEEKREAD(udi->fd, (off_t)0, csd, SGMNT_HDR_LEN, status);
csa->hdr = csd; /* needed for DB_LSEEKWRITE when instance is frozen */
if (0 != status)
{
- gtm_putmsg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
CLOSEFILE_RESET(udi->fd, status); /* resets "udi->fd" to FD_INVALID */
if (0 != status)
- gtm_putmsg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
return FALSE;
}
assert((udi->semid == csd->semid) || (INVALID_SEMID == csd->semid));
@@ -116,14 +116,14 @@ boolean_t db_ipcs_reset(gd_region *reg)
{
if (0 != (save_errno = do_semop(udi->semid, DB_COUNTER_SEM, -1, SEM_UNDO)))
{
- gtm_putmsg(VARLSTCNT(8) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2,
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2,
RTS_ERROR_TEXT("db_ipcs_reset - write semaphore release"), save_errno);
return FALSE;
}
assert(1 == (semval = semctl(udi->semid, DB_CONTROL_SEM, GETVAL)));
if (0 != (save_errno = do_semop(udi->semid, DB_CONTROL_SEM, -1, SEM_UNDO)))
{
- gtm_putmsg(VARLSTCNT(8) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2,
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2,
RTS_ERROR_TEXT("db_ipcs_reset - access control semaphore release"), save_errno);
return FALSE;
}
@@ -147,10 +147,10 @@ boolean_t db_ipcs_reset(gd_region *reg)
DB_LSEEKWRITE(csa, udi->fn, udi->fd, (off_t)0, csd, SGMNT_HDR_LEN, status);
if (0 != status)
{
- gtm_putmsg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
CLOSEFILE_RESET(udi->fd, status); /* resets "udi->fd" to FD_INVALID */
if (0 != status)
- gtm_putmsg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
return FALSE;
}
} else
@@ -162,24 +162,28 @@ boolean_t db_ipcs_reset(gd_region *reg)
if (!get_full_path((char *)DB_STR_LEN(reg), db_ipcs.fn, (unsigned int *)&db_ipcs.fn_len,
GTM_PATH_MAX, &ustatus))
{
- gtm_putmsg(VARLSTCNT(5) ERR_FILEPARSE, 2, DB_LEN_STR(reg), ustatus);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEPARSE, 2, DB_LEN_STR(reg), ustatus);
return FALSE;
}
db_ipcs.fn[db_ipcs.fn_len] = 0;
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa);
- if (0 != (status = send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0)))
+ if (!csa->read_only_fs)
{
- gtm_putmsg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
- CLOSEFILE_RESET(udi->fd, status); /* resets "udi->fd" to FD_INVALID */
+ status = send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0);
if (0 != status)
- gtm_putmsg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
- return FALSE;
+ {
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
+ CLOSEFILE_RESET(udi->fd, status); /* resets "udi->fd" to FD_INVALID */
+ if (0 != status)
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
+ return FALSE;
+ }
}
}
if (0 != sem_rmid(udi->semid))
{
save_errno = errno;
- gtm_putmsg(VARLSTCNT(8) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2,
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2,
RTS_ERROR_TEXT("db_ipcs_reset - sem_rmid"), save_errno);
return FALSE;
}
@@ -188,7 +192,7 @@ boolean_t db_ipcs_reset(gd_region *reg)
udi->counter_acc_incremented = FALSE;
CLOSEFILE_RESET(udi->fd, status); /* resets "udi->fd" to FD_INVALID */
if (0 != status)
- gtm_putmsg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
+ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(reg), status);
/* Since we created the ftok semaphore in mu_rndwn_file, we release/remove it now. But, since we are exiting, we
* do not WAIT for the ftok semaphore if we did not get it in one shot (IPC_NOWAIT). The process that holds the
* ftok will eventually release it and so we are guaranteed that when the last process leaves the database, it will
diff --git a/sr_unix/dm_read.c b/sr_unix/dm_read.c
index 30aab2e..9b92b88 100644
--- a/sr_unix/dm_read.c
+++ b/sr_unix/dm_read.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -54,6 +54,7 @@ GBLREF stack_frame *frame_pointer;
GBLREF spdesc stringpool;
GBLREF unsigned char *msp, *stackbase, *stacktop, *stackwarn;
GBLREF volatile int4 outofband;
+GBLREF boolean_t dmterm_default;
LITREF unsigned char lower_to_upper_table[];
#ifdef UNICODE_SUPPORTED
@@ -275,7 +276,17 @@ void dm_read (mval *v)
cl = clmod(comline_index - index);
}
mask = tt_ptr->term_ctrl;
- mask_term = tt_ptr->mask_term;
+ if (dmterm_default)
+ { /* $view("DMTERM") or gtm_dmterm is set. Ignore the customized terminators; use the default terinators */
+ memset(&mask_term.mask[0], 0, SIZEOF(io_termmask));
+ if (utf8_active)
+ {
+ mask_term.mask[0] = TERM_MSK_UTF8_0;
+ mask_term.mask[4] = TERM_MSK_UTF8_4;
+ } else
+ mask_term.mask[0] = TERM_MSK;
+ } else
+ mask_term = tt_ptr->mask_term;
mask_term.mask[ESC / NUM_BITS_IN_INT4] &= ~(1 << ESC);
ioptr_width = io_ptr->width;
if (!zint_restart)
@@ -627,7 +638,8 @@ void dm_read (mval *v)
continue; /* to allow more input */
}
if ((((int)inchar == tt_ptr->ttio_struct->c_cc[VERASE])
- || ((('\0' == KEY_BACKSPACE[1]) && (inchar == KEY_BACKSPACE[0])))) && !(mask & TRM_PASTHRU))
+ || (((NULL != KEY_BACKSPACE) && ('\0' == KEY_BACKSPACE[1]) && (inchar == KEY_BACKSPACE[0]))))
+ && !(mask & TRM_PASTHRU))
{
if (0 < instr)
{
@@ -782,17 +794,16 @@ void dm_read (mval *v)
}
if ((0 != escape_length) && (FINI <= io_ptr->esc_state))
{
- down = strncmp((const char *)escape_sequence, KEY_DOWN, escape_length);
- up = strncmp((const char *)escape_sequence, KEY_UP, escape_length);
- right = strncmp((const char *)escape_sequence, KEY_RIGHT, escape_length);
- left = strncmp((const char *)escape_sequence, KEY_LEFT, escape_length);
- backspace = delete = insert_key = -1;
- if (NULL != KEY_BACKSPACE)
- backspace = strncmp((const char *)escape_sequence, KEY_BACKSPACE, escape_length);
- if (NULL != KEY_DC)
- delete = strncmp((const char *)escape_sequence, KEY_DC, escape_length);
- if ((NULL != KEY_INSERT) && ('\0' != KEY_INSERT[0]))
- insert_key = strncmp((const char *)escape_sequence, KEY_INSERT, escape_length);
+ /* The arbitrary value -1 signifies inequality in case KEY_* is NULL */
+ down = (NULL != KEY_DOWN) ? strncmp((const char *)escape_sequence, KEY_DOWN, escape_length) : -1;
+ up = (NULL != KEY_UP) ? strncmp((const char *)escape_sequence, KEY_UP, escape_length) : -1;
+ right = (NULL != KEY_RIGHT) ? strncmp((const char *)escape_sequence, KEY_RIGHT, escape_length) : -1;
+ left = (NULL != KEY_LEFT) ? strncmp((const char *)escape_sequence, KEY_LEFT, escape_length) : -1;
+ backspace = (NULL != KEY_BACKSPACE)
+ ? strncmp((const char *)escape_sequence, KEY_BACKSPACE, escape_length) : -1;
+ delete = (NULL != KEY_DC) ? strncmp((const char *)escape_sequence, KEY_DC, escape_length) : -1;
+ insert_key = ((NULL != KEY_INSERT) && ('\0' != KEY_INSERT[0]))
+ ? strncmp((const char *)escape_sequence, KEY_INSERT, escape_length) : -1;
memset(escape_sequence, '\0', escape_length);
escape_length = 0;
if (BADESC == io_ptr->esc_state)
@@ -800,13 +811,11 @@ void dm_read (mval *v)
io_ptr->esc_state = START;
break;
}
- if ((0 == backspace) || (0 == delete))
+ if ((0 == delete) || (0 == backspace))
{
- if (0 < instr)
- {
- MOVE_CURSOR_LEFT_ONE_CHAR(dx, instr, dx_instr, dx_start, ioptr_width);
- DEL_ONE_CHAR_AT_CURSOR(outlen, dx_outlen, dx, dx_instr, dx_start, ioptr_width);
- }
+ if ((0 == backspace) && (0 < instr))
+ MOVE_CURSOR_LEFT_ONE_CHAR(dx, instr, dx_instr, dx_start, ioptr_width)
+ DEL_ONE_CHAR_AT_CURSOR(outlen, dx_outlen, dx, dx_instr, dx_start, ioptr_width);
}
if (0 == insert_key)
insert_mode = !insert_mode; /* toggle */
@@ -814,7 +823,8 @@ void dm_read (mval *v)
{
DOWRITE_A(tt_ptr->fildes, &cr, 1);
WRITE_GTM_PROMPT;
- gtm_tputs(CLR_EOL, 1, outc);
+ if (NULL != CLR_EOL)
+ gtm_tputs(CLR_EOL, 1, outc);
instr = dx_instr = outlen = dx_outlen = 0;
if (0 == up)
{
diff --git a/sr_unix/do_xform.c b/sr_unix/do_xform.c
index a6d0317..bbced96 100644
--- a/sr_unix/do_xform.c
+++ b/sr_unix/do_xform.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,47 +9,71 @@
* *
****************************************************************/
-#include "mdef.h"
+#include "gtm_string.h"
+#include "mdef.h"
#include "gtm_descript.h"
#include "min_max.h"
#include "collseq.h"
#include "do_xform.h"
+#include "memprot.h"
+
+error_def(ERR_COLLARGLONG);
+error_def(ERR_COLTRANSSTR2LONG);
void do_xform(collseq *csp, int fc_type, mstr *input, mstr *output, int *length)
{
gtm32_descriptor outbuff1, insub1;
gtm_descriptor outbuff, insub;
int4 status;
+ char *ba, *addr;
+ DEBUG_ONLY(static boolean_t in_do_xform;)
+ DCL_THREADGBL_ACCESS;
- error_def(ERR_COLLARGLONG);
-
+ SETUP_THREADGBL_ACCESS;
+ assert(!in_do_xform);
DO_XFORM_RETURN_IF_NULL_STRING(input, output, length);
+ DEBUG_ONLY(in_do_xform = TRUE;)
assert (0 == csp->argtype || 1 == csp->argtype);
assert(XFORM == fc_type || XBACK == fc_type);
if (0 == csp->argtype)
{
if (MAX_STRLEN_32K < input->len)
- rts_error(VARLSTCNT(3) ERR_COLLARGLONG, 1, csp->act);
+ {
+ DEBUG_ONLY(in_do_xform = FALSE;)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_COLLARGLONG, 1, csp->act);
+ }
insub.type = DSC_K_DTYPE_T;
insub.len = input->len;
insub.val = input->addr;
outbuff.type = DSC_K_DTYPE_T;
outbuff.len = MIN(output->len, MAX_STRLEN_32K);
- outbuff.val = output->addr;
+ memprot(&(TREF(protmem_ba)), outbuff.len);
+ ba = (TREF(protmem_ba)).addr;
+ assert(NULL != ba);
+ outbuff.val = (NULL != ba) ? ba : output->addr;
if (XFORM == fc_type)
status = (csp->xform)(&insub, 1, &outbuff, length);
else
status = (csp->xback)(&insub, 1, &outbuff, length);
+
+ if (*length > output->len)
+ {
+ DEBUG_ONLY(in_do_xform = FALSE;)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_COLTRANSSTR2LONG, 1, csp->act);
+ }
/* If collation routine has changed outbuff.val (which it will if it cannot store the transformed
* result in the buffer that is passed in), the transformed value is stored in the buffer allocated
* externally by the collation routine. In this case, update output->addr before returning. */
- if (outbuff.val != output->addr)
- {
- assert(outbuff.len > MIN(output->len, MAX_STRLEN_32K));
+ addr = (NULL != ba) ? ba : output->addr;
+ if (outbuff.val != addr)
output->addr = outbuff.val;
+ else if (NULL != ba)
+ {
+ assert(*length <= outbuff.len);
+ memcpy(output->addr, ba, *length);
}
} else
{
@@ -59,21 +83,34 @@ void do_xform(collseq *csp, int fc_type, mstr *input, mstr *output, int *length)
outbuff1.type = DSC_K_DTYPE_T;
outbuff1.len = output->len;
- outbuff1.val = output->addr;
+ memprot(&(TREF(protmem_ba)), outbuff1.len);
+ ba = (TREF(protmem_ba)).addr;
+ assert(NULL != ba);
+ outbuff1.val = (NULL != ba) ? ba : output->addr;
if (XFORM == fc_type)
status = (csp->xform)(&insub1, 1, &outbuff1, length);
else
status = (csp->xback)(&insub1, 1, &outbuff1, length);
+
+ if (*length > output->len)
+ {
+ DEBUG_ONLY(in_do_xform = FALSE;)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_COLTRANSSTR2LONG, 1, csp->act);
+ }
/* If collation routine has changed outbuff1.val (which it will if it cannot store the transformed
* result in the buffer that is passed in), the transformed value is stored in the buffer allocated
* externally by the collation routine. In this case, update output->addr before returning. */
- if (outbuff1.val != output->addr)
- {
- assert(outbuff1.len > output->len);
+ addr = (NULL != ba) ? ba : output->addr;
+ if (outbuff1.val != addr)
output->addr = outbuff1.val;
+ else if (NULL != ba)
+ {
+ assert(*length <= outbuff1.len);
+ memcpy(output->addr, ba, *length);
}
}
+ DEBUG_ONLY(in_do_xform = FALSE;)
if (status)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
diff --git a/sr_unix/dse.c b/sr_unix/dse.c
index aad0502..e2b2bd8 100644
--- a/sr_unix/dse.c
+++ b/sr_unix/dse.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -49,7 +49,6 @@
#include "compiler.h"
#include "patcode.h"
#include "lke.h"
-#include "get_page_size.h"
#include "gtm_startup_chk.h"
#include "generic_signal_handler.h"
#include "init_secshr_addrs.h"
@@ -57,12 +56,10 @@
#include "getzdir.h"
#include "dse_exit.h"
#include "getjobname.h"
-#include "getjobnum.h"
#include "sig_init.h"
#include "gtmmsg.h"
#include "suspsigs_handler.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
#include "wbox_test_init.h"
#include "gtmio.h"
@@ -105,13 +102,11 @@ int main(int argc, char *argv[])
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- set_blocksig();
- gtm_imagetype_init(DSE_IMAGE);
- gtm_wcswidth_fnptr = gtm_wcswidth;
- gtm_env_init(); /* read in all environment variables */
+ common_startup_init(DSE_IMAGE);
licensed = TRUE;
TREF(transform) = TRUE;
TREF(no_spangbls) = TRUE; /* dse operates on a per-region basis irrespective of global mapping in gld */
+ TREF(skip_file_corrupt_check) = TRUE; /* do not let csd->file_corrupt flag cause errors in dse */
op_open_ptr = op_open;
patch_curr_blk = get_dir_root();
err_init(util_base_ch);
@@ -120,7 +115,6 @@ int main(int argc, char *argv[])
sig_init(generic_signal_handler, dse_ctrlc_handler, suspsigs_handler, continue_handler);
atexit(util_exit_handler);
SET_LATCH_GLOBAL(&defer_latch, LOCK_AVAILABLE);
- get_page_size();
stp_init(STP_INITSIZE);
rts_stringpool = stringpool;
getjobname();
@@ -132,7 +126,6 @@ int main(int argc, char *argv[])
initialize_pattern_table();
gvinit();
region_init(FALSE);
- getjobnum();
util_out_print("!/File !_!AD", TRUE, DB_LEN_STR(gv_cur_region));
util_out_print("Region!_!AD!/", TRUE, REG_LEN_STR(gv_cur_region));
cli_lex_setup(argc, argv);
@@ -166,6 +159,7 @@ int main(int argc, char *argv[])
}
dse_exit();
REVERT;
+ return 0;
}
static void display_prompt(void)
diff --git a/sr_unix/dse_cmd.c b/sr_unix/dse_cmd.c
index 48d66f1..65765e0 100644
--- a/sr_unix/dse_cmd.c
+++ b/sr_unix/dse_cmd.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -352,6 +352,7 @@ static readonly CLI_ENTRY dse_save_qual[] = {
static readonly CLI_ENTRY dse_shift_qual[] = {
{ "BACKWARD", 0, 0, 0, 0, 0, 0, VAL_REQ, 0, NON_NEG, VAL_NUM, VAL_HEX },
+{ "BLOCK", 0, 0, 0, 0, 0, 0, VAL_REQ, 0, NON_NEG, VAL_NUM, VAL_HEX },
{ "FORWARD", 0, 0, 0, 0, 0, 0, VAL_REQ, 0, NON_NEG, VAL_NUM, VAL_HEX },
{ "OFFSET", 0, 0, 0, 0, 0, 0, VAL_REQ, 0, NON_NEG, VAL_NUM, VAL_HEX },
{ 0 }
diff --git a/sr_unix/dse_open.c b/sr_unix/dse_open.c
index 11d3e15..dc34309 100644
--- a/sr_unix/dse_open.c
+++ b/sr_unix/dse_open.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -74,6 +74,7 @@ void dse_open (void)
{
(unsigned char)iop_newversion,
(unsigned char)iop_m,
+ (unsigned char)iop_stream,
(unsigned char)iop_nowrap,
(unsigned char)iop_eol
};
@@ -83,10 +84,11 @@ void dse_open (void)
{
(unsigned char)iop_width,
# ifdef BIGENDIAN
- (unsigned char)0x0, (unsigned char)0x10, (unsigned char)0x0, (unsigned char)0x0
+ (unsigned char)0x0, (unsigned char)0x10, (unsigned char)0x0, (unsigned char)0x0,
# else
- (unsigned char)0x0, (unsigned char)0x0, (unsigned char)0x10, (unsigned char)0x0
+ (unsigned char)0x0, (unsigned char)0x0, (unsigned char)0x10, (unsigned char)0x0,
# endif
+ (unsigned char)iop_eol
};
if (cli_present("FILE") == CLI_PRESENT)
diff --git a/sr_unix/errorsp.h b/sr_unix/errorsp.h
index 10d1bc5..8a36998 100644
--- a/sr_unix/errorsp.h
+++ b/sr_unix/errorsp.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,6 +16,9 @@
#include "gtm_stdio.h"
#include "have_crit.h"
+#include "gtmimagename.h"
+#include <rtnhdr.h>
+#include "stack_frame.h"
#ifdef __MVS__
# define GTMCORENAME "gtmcore"
@@ -56,10 +59,19 @@
#define TPRESTART_ARG_CNT 6
typedef void ch_ret_type;
+
+/* Note that the condition_handler structure layout is relied upon by assembly code (see chnd_size, chnd_* in error.si).
+ * Any changes here need corresponding changes in error.si.
+ */
typedef struct condition_handler_struct
{
struct condition_handler_struct *save_active_ch; /* -> Previous active condition handler */
boolean_t ch_active; /* True when *THIS* condition handler is active (not usable) */
+ uint4 dollar_tlevel; /* $tlevel at time of ESTABLISH; needed at UNWIND time.
+ * Used only in DEBUG code. But defined in PRO to keep error.si
+ * simple (it keeps track of offsets of members in structures
+ * and we dont want it to be conditional on PRO vs DBG).
+ */
ch_ret_type (*ch)(); /* Condition handler address */
jmp_buf jmp; /* setjmp/longjmp buffer associated with ESTABLISH point */
} condition_handler;
@@ -142,7 +154,7 @@ void ch_trace_point() {return;}
GBLREF int process_exiting; \
\
assert(!process_exiting); \
- CHTRACEPOINT; \
+ CHTRACEPOINT; \
for ( ;(ctxt > &chnd[0]) && (ctxt->ch != &mdb_condition_handler); ctxt--); \
CHECKLOWBOUND(ctxt); \
assert((ctxt->ch == &mdb_condition_handler) \
@@ -151,7 +163,7 @@ void ch_trace_point() {return;}
assertpro(!(SFF_IMPLTSTART_CALLD & frame_pointer->flags) || (0 != proc_act_type) \
|| (SFF_ETRAP_ERR & frame_pointer->flags)); \
DBGEHND((stderr, "MUM_TSTART: Frame 0x"lvaddr" dispatched\n", frame_pointer)); \
- ctxt->ch_active = FALSE; \
+ ctxt->ch_active = FALSE; \
restart = mum_tstart; \
active_ch = ctxt; \
longjmp(ctxt->jmp, 1); \
@@ -161,13 +173,13 @@ void ch_trace_point() {return;}
GBLREF int process_exiting; \
\
assert(!process_exiting); \
- CHTRACEPOINT; \
+ CHTRACEPOINT; \
for ( ;ctxt > &chnd[0] && ctxt->ch != &mdb_condition_handler; ctxt--); \
CHECKLOWBOUND(ctxt); \
assert((ctxt->ch == &mdb_condition_handler) \
&& (FALSE == ctxt->save_active_ch->ch_active)); \
DBGEHND((stderr, "MUM_TSTART: Frame 0x"lvaddr" dispatched\n", frame_pointer)); \
- ctxt->ch_active = FALSE; \
+ ctxt->ch_active = FALSE; \
restart = mum_tstart; \
active_ch = ctxt; \
longjmp(ctxt->jmp, 1); \
@@ -175,13 +187,16 @@ void ch_trace_point() {return;}
#endif
#define GTM_ASM_ESTABLISH { /* So named because gtm_asm_establish does exactly this */ \
+ GBLREF uint4 dollar_tlevel; \
+ \
CHTRACEPOINT; \
ctxt++; \
if (ctxt >= (chnd_end + (!process_exiting ? 0 : CONDSTK_RESERVE))) \
condstk_expand(); \
- CHECKHIGHBOUND(ctxt); \
- ctxt->save_active_ch = active_ch; \
- ctxt->ch_active = FALSE; \
+ CHECKHIGHBOUND(ctxt); \
+ ctxt->save_active_ch = active_ch; \
+ ctxt->ch_active = FALSE; \
+ DEBUG_ONLY(ctxt->dollar_tlevel = dollar_tlevel;) \
active_ch = ctxt; \
}
#define ESTABLISH_NOJMP(x) { \
@@ -220,19 +235,19 @@ void ch_trace_point() {return;}
#endif
#define REVERT { \
- CHTRACEPOINT; \
+ CHTRACEPOINT; \
active_ch = ctxt->save_active_ch; \
CHECKHIGHBOUND(active_ch); \
CHECKLOWBOUND(active_ch); \
ctxt--; \
- CHECKLOWBOUND(ctxt); \
+ CHECKLOWBOUND(ctxt); \
}
#define CONTINUE { \
- CHTRACEPOINT; \
+ CHTRACEPOINT; \
active_ch++; \
- CHECKHIGHBOUND(active_ch); \
- chnd[current_ch].ch_active = FALSE; \
+ CHECKHIGHBOUND(active_ch); \
+ chnd[current_ch].ch_active = FALSE; \
return; \
}
@@ -261,12 +276,12 @@ void ch_trace_point() {return;}
stop_image_ch(); \
} \
assert((SUCCESS == SEVERITY) || (INFO == SEVERITY)); \
- }
+ }
#define NEXTCH { \
- CHTRACEPOINT; \
- chnd[current_ch].ch_active = FALSE; \
- DRIVECH(arg); \
+ CHTRACEPOINT; \
+ chnd[current_ch].ch_active = FALSE; \
+ DRIVECH(arg); \
/* If ever DRIVECH does a CONTINUE and returns back to us, we \
* need to do a CONTINUE as well so we re-establish ourselves \
* on the condition handler stack. This cancels out the \
@@ -284,39 +299,56 @@ void ch_trace_point() {return;}
/* Should never unwind a condition handler established with ESTABLISH_NOUNWIND. Currently t_ch and dbinit_ch are the only ones. */
#define UNWINDABLE(unw_ch) ((&t_ch != unw_ch->ch) && (&dbinit_ch != unw_ch->ch))
#define UNWIND(dummy1, dummy2) { \
- GBLREF int process_exiting; \
- GBLREF boolean_t ok_to_UNWIND_in_exit_handling; \
+ GBLREF int process_exiting; \
+ GBLREF boolean_t ok_to_UNWIND_in_exit_handling; \
+ GBLREF volatile boolean_t in_wcs_recover; \
+ GBLREF uint4 dollar_tlevel; \
\
assert(!process_exiting || ok_to_UNWIND_in_exit_handling); \
/* When we hit an error in the midst of commit, t_ch/t_commit_cleanup should be invoked \
* and clean it up before any condition handler on the stack unwinds. \
*/ \
- assert(0 == have_crit(CRIT_IN_COMMIT)); \
- CHTRACEPOINT; \
- chnd[current_ch].ch_active = FALSE; \
+ assert((0 == have_crit(CRIT_IN_COMMIT)) || in_wcs_recover); \
+ CHTRACEPOINT; \
+ chnd[current_ch].ch_active = FALSE; \
active_ch++; \
- CHECKHIGHBOUND(active_ch); \
+ CHECKHIGHBOUND(active_ch); \
ctxt = active_ch; \
assert(UNWINDABLE(active_ch)); \
+ assert(active_ch->dollar_tlevel == dollar_tlevel); \
longjmp(active_ch->jmp, -1); \
}
-#define START_CH(flag_assert) int current_ch; \
- DCL_THREADGBL_ACCESS; \
- \
- SETUP_THREADGBL_ACCESS; \
- CHTRACEPOINT; \
- current_ch = (active_ch - chnd); \
- active_ch->ch_active = TRUE; \
- active_ch--; \
- CHECKLOWBOUND(active_ch); \
- DBGEHND((stderr, "%s: Condition handler entered at line %d - arg: %d SIGNAL: %d\n", \
- __FILE__, __LINE__, arg, SIGNAL)); \
- if ((flag_assert) && ((SUCCESS == SEVERITY) || (INFO == SEVERITY))) \
- { \
- PRN_ERROR; \
- CONTINUE; \
- }
+/* This macro short-circuits the condition_handler for INFO or SUCCESS errors other than CTRLC and CTRLY and returns control
+ * to the command after the rts_error_csa invocation, which is what the base condition handler (mdb_condition_handler or util_ch)
+ * would do anyway, but if we are going to return control we don't want any condition handlers messing with state.
+ * The base condition handlers and other code in the utilities have special logic to treat CTRLC and CTRLY as operator
+ * actions with a semantic significance, so this macro does not intercept those.
+ * In the MUMPS run-time, unless in a direct mode frame, we skip displaying the error because we don't want to mess with
+ * the application's design for user interaction.
+ */
+#define START_CH(continue_on_success) /* info is a form of success */ \
+ GBLREF boolean_t ctrlc_on; \
+ error_def(ERR_CTRLC); /* BYPASSOK */ \
+ error_def(ERR_CTRLY); /* BYPASSOK */ \
+ int current_ch; \
+ DCL_THREADGBL_ACCESS; \
+ \
+ SETUP_THREADGBL_ACCESS; \
+ CHTRACEPOINT; \
+ current_ch = (active_ch - chnd); \
+ active_ch->ch_active = TRUE; \
+ active_ch--; \
+ CHECKLOWBOUND(active_ch); \
+ DBGEHND((stderr, "%s: Condition handler entered at line %d - arg: %d SIGNAL: %d\n", \
+ __FILE__, __LINE__, arg, SIGNAL)); \
+ if ((continue_on_success) && ((SUCCESS == SEVERITY) || (INFO == SEVERITY) \
+ && ((int)ERR_CTRLY != SIGNAL) && ((int)ERR_CTRLC != SIGNAL))) \
+ { \
+ if (ctrlc_on || !IS_GTM_IMAGE) \
+ PRN_ERROR; \
+ CONTINUE; \
+ }
#define MDB_START
@@ -325,11 +357,11 @@ void stop_image_conditional_core(void);
void stop_image_no_core(void);
#define TERMINATE { \
- CHTRACEPOINT; \
+ CHTRACEPOINT; \
if (SUPPRESS_DUMP) \
- stop_image_no_core(); \
+ stop_image_no_core(); \
else \
- stop_image(); \
+ stop_image(); \
}
#define SUPPRESS_DUMP (created_core || dont_want_core)
@@ -337,8 +369,8 @@ void stop_image_no_core(void);
#define MUMPS_EXIT { \
GBLREF int4 exi_condition; \
- GBLREF int mumps_status; \
- CHTRACEPOINT; \
+ GBLREF int mumps_status; \
+ CHTRACEPOINT; \
mumps_status = SIGNAL; \
exi_condition = -mumps_status; \
EXIT(-exi_condition); \
@@ -365,9 +397,10 @@ error_def(ERR_OUTOFSPACE);
|| SIGNAL == (int)ERR_STACKOFLOW)
/* true if above or SEVERE and GTM error (perhaps add some "system" errors) */
-#define DUMPABLE ( DUMP || \
- ( SEVERITY == SEVERE && IS_GTM_ERROR(SIGNAL) \
- && SIGNAL != (int)ERR_OUTOFSPACE) )
+#define DUMPABLE ((SEVERITY == SEVERE) && IS_GTM_ERROR(SIGNAL) \
+ && (SIGNAL != (int)ERR_OUTOFSPACE) \
+ DEBUG_ONLY(&& (WBTEST_ENABLED(WBTEST_SKIP_CORE_FOR_MEMORY_ERROR) \
+ ? (!process_exiting || (SIGNAL != (int)ERR_MEMORY)) : TRUE)))
unsigned char *set_zstatus(mstr *src, int arg, unsigned char **ctxtp, boolean_t need_rtsloc);
diff --git a/sr_unix/fake_enospc.c b/sr_unix/fake_enospc.c
new file mode 100644
index 0000000..ae13b8a
--- /dev/null
+++ b/sr_unix/fake_enospc.c
@@ -0,0 +1,161 @@
+/****************************************************************
+ * *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#ifdef DEBUG /* The #ifdef DEBUG game is to basically leave a return statement, so picky compilers are satisfied */
+#include "mdef.h"
+
+#include "gtm_stat.h"
+#include "gtm_fcntl.h"
+
+#include "gdsroot.h"
+#include "gdsbt.h"
+#include "gtm_facility.h"
+#include "fileinfo.h"
+#include "gdsfhead.h"
+#include "filestruct.h"
+#include "jnl.h"
+#include "gtmio.h" /* for CLOSEFILE used by the F_CLOSE macro in JNL_FD_CLOSE */
+#include "repl_sp.h" /* for F_CLOSE used by the JNL_FD_CLOSE macro */
+#include "iosp.h" /* for SS_NORMAL used by the JNL_FD_CLOSE macro */
+#include "gt_timer.h"
+#include "gtmimagename.h"
+#include "dpgbldir.h"
+#include "have_crit.h"
+#include "anticipatory_freeze.h"
+#endif
+#include "fake_enospc.h"
+#ifdef DEBUG
+GBLREF boolean_t is_jnlpool_creator; /* The purpose of this check is to assign only one process responsible of
+ * setting fake ENOSPC flags. If we had multiple processes messing with,
+ * FREEZE the test would freeze more often and eventually do nothing but
+ * freeze.
+ */
+GBLREF jnlpool_addrs jnlpool;
+GBLREF volatile int4 gtmMallocDepth;
+GBLREF volatile uint4 heartbeat_counter;
+
+STATICDEF uint4 next_heartbeat_counter = 1; /* the heartbeat_counter at which enospc manipulations need to happen */
+STATICDEF uint4 syslog_deferred = 0;
+
+error_def(ERR_TEXT);
+error_def(ERR_FAKENOSPCLEARED);
+
+#define ENOSPC_FROZEN_DURATION 2 /* 16 seconds */
+#define ENOSPC_UNFROZEN_DURATION (2 * (rand() % 120 + 1)) /* 16 seconds to 32 minutes */
+#define MAX_REGIONS 50
+#define NONE 0 /* 1/2 probablility */
+#define DB_ON 1 /* 1/6 probablility */
+#define JNL_ON 2 /* 1/6 probablility */
+#define DB_AND_JNL_ON 3 /* 1/6 probablility */
+#define MAX_ENOSPC_TARGET 4
+#endif
+
+void fake_enospc()
+{
+# ifdef DEBUG
+ boolean_t ok_to_interrupt, is_time_to_act;
+ char enospc_enable_list[MAX_REGIONS];
+ const char *syslog_msg;
+ gd_addr *addr_ptr;
+ gd_region *r_local, *r_top;
+ int i;
+ sgmnt_addrs *csa;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ if (TREF(gtm_test_fake_enospc) && is_jnlpool_creator && CUSTOM_ERRORS_LOADED)
+ {
+ ok_to_interrupt = (INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) && (0 == gtmMallocDepth);
+ is_time_to_act = (next_heartbeat_counter == heartbeat_counter);
+ if (syslog_deferred && ok_to_interrupt)
+ {
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_FAKENOSPCLEARED, 1, (heartbeat_counter - syslog_deferred));
+ syslog_deferred = 0;
+ }
+ if (!is_time_to_act || syslog_deferred || (!ok_to_interrupt && !IS_REPL_INST_FROZEN))
+ { /* We have to skip this because we have just fallen into deferred zone or we are currently in it */
+ if (is_time_to_act)
+ next_heartbeat_counter++; /* Try again in the next heartbeat */
+ return;
+ }
+ assert(0 == syslog_deferred);
+ srand(time(NULL));
+ addr_ptr = get_next_gdr(NULL);
+ if (NULL == addr_ptr) /* Ensure that there is a global directory to operate on. */
+ return;
+ assert(NULL == get_next_gdr(addr_ptr));
+ /* Randomly simulate ENOSPC or free space. NO more than 50 regions are allowed to avoid unnecessary
+ * malloc/frees in debug-only code
+ */
+ assert(MAX_REGIONS >= addr_ptr->n_regions);
+ if (!IS_REPL_INST_FROZEN)
+ { /* We are in an UNFROZEN state, and about to be FROZEN due to ENOSPC */
+ assert(MAX_REGIONS >= addr_ptr->n_regions);
+ for (i = 0; i < addr_ptr->n_regions; i++)
+ {
+ if (rand() % 2) /* Should we trigger fake ENOSPC on this region */
+ enospc_enable_list[i] = rand() % (MAX_ENOSPC_TARGET - 1) + 1; /* What kind? */
+ else
+ enospc_enable_list[i] = NONE;
+ }
+ next_heartbeat_counter = heartbeat_counter + ENOSPC_FROZEN_DURATION;
+ } else
+ { /* We are in a FROZEN state, and about to be UNFROZEN due to free space */
+ memset(enospc_enable_list, 0, MAX_REGIONS);
+ next_heartbeat_counter = heartbeat_counter + ENOSPC_UNFROZEN_DURATION;
+ if (!ok_to_interrupt)
+ syslog_deferred = heartbeat_counter;
+ }
+ for (r_local = addr_ptr->regions, r_top = r_local + addr_ptr->n_regions, i = 0; r_local < r_top; r_local++, i++)
+ {
+ if ((dba_bg != r_local->dyn.addr->acc_meth) && (dba_mm != r_local->dyn.addr->acc_meth))
+ continue;
+ csa = REG2CSA(r_local);
+ if ((NULL != csa) && (NULL != csa->nl) && INST_FREEZE_ON_NOSPC_ENABLED(csa))
+ {
+ syslog_msg = NULL;
+ switch(enospc_enable_list[i])
+ {
+ case NONE:
+ if (csa->nl->fake_db_enospc || csa->nl->fake_jnl_enospc)
+ {
+ syslog_msg = "Turning off fake ENOSPC for both database and journal file.";
+ csa->nl->fake_db_enospc = FALSE;
+ csa->nl->fake_jnl_enospc = FALSE;
+ }
+ break;
+ case DB_ON:
+ syslog_msg = "Turning on fake ENOSPC only for database file.";
+ csa->nl->fake_db_enospc = TRUE;
+ csa->nl->fake_jnl_enospc = FALSE;
+ break;
+ case JNL_ON:
+ syslog_msg = "Turning on fake ENOSPC only for journal file.";
+ csa->nl->fake_db_enospc = FALSE;
+ csa->nl->fake_jnl_enospc = TRUE;
+ break;
+ case DB_AND_JNL_ON:
+ syslog_msg = "Turning on fake ENOSPC for both database and journal file.";
+ csa->nl->fake_db_enospc = TRUE;
+ csa->nl->fake_jnl_enospc = TRUE;
+ break;
+ default:
+ assert(FALSE);
+ }
+ if (ok_to_interrupt && (NULL != syslog_msg))
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_TEXT, 2, DB_LEN_STR(r_local), ERR_TEXT, 2,
+ LEN_AND_STR(syslog_msg));
+ }
+ }
+ }
+# endif
+ return;
+}
diff --git a/sr_avms/release_name.h b/sr_unix/fake_enospc.h
similarity index 71%
copy from sr_avms/release_name.h
copy to sr_unix/fake_enospc.h
index 150f221..5832f07 100644
--- a/sr_avms/release_name.h
+++ b/sr_unix/fake_enospc.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,6 +9,8 @@
* *
****************************************************************/
-#define GTM_RELEASE_NAME "GT.M V6.1-000 VMS AXP"
-#define GTM_PRODUCT "GT.M"
-#define GTM_VERSION "V6.1"
+#ifndef _FAKE_ENOSPC_H
+#define _FAKE_ENOSPC_H
+
+void fake_enospc(void);
+#endif
diff --git a/sr_unix/fgn_getinfo.c b/sr_unix/fgn_getinfo.c
index 053c55a..f2f7d1e 100644
--- a/sr_unix/fgn_getinfo.c
+++ b/sr_unix/fgn_getinfo.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,8 +22,13 @@
#include "gtmmsg.h"
#include "error.h"
+error_def(ERR_DLLNOCLOSE);
+error_def(ERR_DLLNOOPEN);
+error_def(ERR_DLLNORTN);
+error_def(ERR_TEXT);
+
/* below comments applicable only to tru64 */
-/* dlsym() is bound to return short pointer because of -taso loader flag. GTMASSERT on this assumption.
+/* dlsym() is bound to return short pointer because of -taso loader flag
* dlopen() returns a long pointer. All the callers of fgn_getpak() should take care of this.
* dlclose() uses the handle generated above. So, the same semantics apply.
* dlerror() returns a char pointer, which is again long.
@@ -48,8 +53,6 @@ void_ptr_t fgn_getpak(char *package_name, int msgtype)
void_ptr_t ret_handle;
char_ptr_t dummy_err_str;
char err_str[MAX_ERRSTR_LEN]; /* needed as util_out_print doesn't handle 64bit pointers */
- error_def(ERR_TEXT);
- error_def(ERR_DLLNOOPEN);
if (!(ret_handle = dlopen(package_name, RTLD_LAZY)))
{
@@ -57,8 +60,12 @@ void_ptr_t fgn_getpak(char *package_name, int msgtype)
{
assert(!(msgtype & ~SEV_MSK));
COPY_DLLERR_MSG(dummy_err_str, err_str);
- rts_error(VARLSTCNT(8) MAKE_MSG_TYPE(ERR_DLLNOOPEN, msgtype), 2, LEN_AND_STR(package_name),
- ERR_TEXT, 2, LEN_AND_STR(err_str));
+ if ((INFO == msgtype))
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) MAKE_MSG_TYPE(ERR_DLLNOOPEN, msgtype),
+ 2, LEN_AND_STR(package_name), ERR_TEXT, 2, LEN_AND_STR(err_str));
+ else
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) MAKE_MSG_TYPE(ERR_DLLNOOPEN, msgtype),
+ 2, LEN_AND_STR(package_name), ERR_TEXT, 2, LEN_AND_STR(err_str));
}
}
return ret_handle;
@@ -77,8 +84,6 @@ fgnfnc fgn_getrtn(void_ptr_t package_handle, mstr *entry_name, int msgtype)
char_ptr_t dummy_err_str;
void *short_sym_addr;
char err_str[MAX_ERRSTR_LEN]; /* needed as util_out_print doesn't handle 64bit pointers */
- error_def(ERR_DLLNORTN);
- error_def(ERR_TEXT);
if (!(sym_addr = dlsym(package_handle, entry_name->addr)))
{
@@ -86,8 +91,12 @@ fgnfnc fgn_getrtn(void_ptr_t package_handle, mstr *entry_name, int msgtype)
{
assert(!(msgtype & ~SEV_MSK));
COPY_DLLERR_MSG(dummy_err_str, err_str);
- rts_error(VARLSTCNT(8) MAKE_MSG_TYPE(ERR_DLLNORTN, msgtype), 2, LEN_AND_STR(entry_name->addr),
- ERR_TEXT, 2, LEN_AND_STR(err_str));
+ if ((INFO == msgtype))
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) MAKE_MSG_TYPE(ERR_DLLNORTN, msgtype),
+ 2, LEN_AND_STR(entry_name->addr), ERR_TEXT, 2, LEN_AND_STR(err_str));
+ else
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) MAKE_MSG_TYPE(ERR_DLLNORTN, msgtype),
+ 2, LEN_AND_STR(entry_name->addr), ERR_TEXT, 2, LEN_AND_STR(err_str));
}
} else
{ /* Tru64 - dlsym() is bound to return short pointer because of ld -taso flag used for GT.M */
@@ -98,7 +107,7 @@ fgnfnc fgn_getrtn(void_ptr_t package_handle, mstr *entry_name, int msgtype)
sym_addr = NULL;
/* always report an error irrespective of msgtype - since this code should never
* have executed and/or the DLL might need to be rebuilt with 32-bit options */
- rts_error(VARLSTCNT(8) ERR_DLLNORTN, 2, LEN_AND_STR(entry_name->addr),
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_DLLNORTN, 2, LEN_AND_STR(entry_name->addr),
ERR_TEXT, 2, LEN_AND_LIT("Symbol is loaded above the lower 31-bit address space"));
}
#endif
@@ -111,14 +120,17 @@ void fgn_closepak(void_ptr_t package_handle, int msgtype)
char_ptr_t dummy_err_str;
int status;
char err_str[MAX_ERRSTR_LEN];
- error_def(ERR_TEXT);
- error_def(ERR_DLLNOCLOSE);
status = dlclose(package_handle);
if (0 != status && SUCCESS != msgtype)
{
assert(!(msgtype & ~SEV_MSK));
COPY_DLLERR_MSG(dummy_err_str, err_str);
- rts_error(VARLSTCNT(6) MAKE_MSG_TYPE(ERR_DLLNOCLOSE, msgtype), 0, ERR_TEXT, 2, LEN_AND_STR(err_str));
+ if ((INFO == msgtype))
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) MAKE_MSG_TYPE(ERR_DLLNOCLOSE, msgtype), 0,
+ ERR_TEXT, 2, LEN_AND_STR(err_str));
+ else
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) MAKE_MSG_TYPE(ERR_DLLNOCLOSE, msgtype), 0,
+ ERR_TEXT, 2, LEN_AND_STR(err_str));
}
}
diff --git a/sr_unix/file_input.c b/sr_unix/file_input.c
index 8272566..2af5488 100644
--- a/sr_unix/file_input.c
+++ b/sr_unix/file_input.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -47,7 +47,7 @@ static char *load_fn_ptr;
static int load_fn_len;
static readonly unsigned char open_params_list[] =
{
- (unsigned char)iop_recordsize, /* 64K - 2 - big enough for MAX_BLK_SZ */
+ (unsigned char)iop_recordsize, /* 64K enough to hold MAX_BLK_SZ */
# ifdef BIGENDIAN
(unsigned char)0, (unsigned char)0, (unsigned char)255, (unsigned char)255,
# else
@@ -56,6 +56,7 @@ static readonly unsigned char open_params_list[] =
(unsigned char)iop_readonly,
(unsigned char)iop_rewind,
(unsigned char)iop_m,
+ /* iop_stream not included since it is necessary only if we are opening file for write (which is not the case here) */
(unsigned char)iop_nowrap,
(unsigned char)iop_eol
};
@@ -102,10 +103,10 @@ void file_input_close(void)
op_close(&val, &pars);
}
-int file_input_bin_get(char **in_ptr, ssize_t *file_offset, char **buff_base)
+int file_input_bin_get(char **in_ptr, ssize_t *file_offset, char **buff_base, boolean_t do_rts_error)
{
char *ptr;
- int rd_cnt, rd_len, s1;
+ int rd_cnt, rd_len, ret, s1;
unsigned short s1s;
ESTABLISH_RET(mupip_load_ch, 0);
@@ -113,14 +114,23 @@ int file_input_bin_get(char **in_ptr, ssize_t *file_offset, char **buff_base)
{
if (0 >= (rd_len = file_input_bin_read())) /* NOTE assignment */
{
+ ret = 0;
if (buff1_end != buff1_ptr)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_PREMATEOF);
- else if (-1 == rd_len)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_LOADFILERR, 2, load_fn_len, load_fn_ptr);
- else
+ {
+ if (do_rts_error)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_PREMATEOF);
+ ret = ERR_PREMATEOF;
+ }
+ else if (-1 == rd_len)
+ {
+ if (do_rts_error)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_LOADFILERR, 2, load_fn_len, load_fn_ptr);
+ ret = ERR_LOADFILERR;
+ }
+ if (!do_rts_error || 0 == ret)
{
REVERT;
- return 0;
+ return -ret;
}
}
buff1_end += rd_len;
@@ -136,9 +146,17 @@ int file_input_bin_get(char **in_ptr, ssize_t *file_offset, char **buff_base)
rd_len = file_input_bin_read();
if ((rd_len + buff1_end - buff1_ptr) < s1)
{
+ if (!do_rts_error)
+ REVERT;
if (-1 == rd_len)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_LOADFILERR, 2, load_fn_len, load_fn_ptr);
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_PREMATEOF);
+ {
+ if (do_rts_error)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_LOADFILERR, 2, load_fn_len, load_fn_ptr);
+ return -ERR_LOADFILERR;
+ }
+ if (do_rts_error)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_PREMATEOF);
+ return -ERR_PREMATEOF;
}
buff1_end += rd_len;
}
@@ -198,7 +216,7 @@ int file_input_get(char **in_ptr)
}
if (mbuff_len < ret_len + rd_len)
{
- new_mbuff_len = MAX(ret_len,(2 * mbuff_len));
+ new_mbuff_len = MAX((ret_len + rd_len), (2 * mbuff_len));
tmp_ptr = (char *)malloc(new_mbuff_len);
if (NULL == tmp_ptr)
{
@@ -209,10 +227,8 @@ int file_input_get(char **in_ptr)
{
memcpy(tmp_ptr, mbuff, (ret_len));
free (mbuff);
- }
- else
+ } else
memcpy(tmp_ptr, buff1, (ret_len));
-
mbuff = tmp_ptr;
mbuff_len = new_mbuff_len;
diff --git a/sr_unix/file_input.h b/sr_unix/file_input.h
index 99101e9..c8558ab 100644
--- a/sr_unix/file_input.h
+++ b/sr_unix/file_input.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2012 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,8 +14,11 @@
void file_input_init(char *fn, short fn_len);
void file_input_close(void);
-int file_input_bin_get(char **in_ptr, ssize_t *file_offset, char **buff_base);
+int file_input_bin_get(char **in_ptr, ssize_t *file_offset, char **buff_base, boolean_t do_rts_error);
int file_input_bin_read(void);
int file_input_get(char **in_ptr);
+#define DO_RTS_ERROR_TRUE TRUE
+#define DO_RTS_ERROR_FALSE FALSE
+
#endif
diff --git a/sr_unix/find_reg_hash_idx.c b/sr_unix/find_reg_hash_idx.c
new file mode 100644
index 0000000..6404456
--- /dev/null
+++ b/sr_unix/find_reg_hash_idx.c
@@ -0,0 +1,28 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+#include "mdef.h"
+#include "gdsroot.h"
+#include "gdsbt.h"
+#include "gdsfhead.h"
+#include "muextr.h"
+
+GBLDEF gd_addr *gd_header;
+
+/* This routine finds the position of a region in the global directory which we use to index arrays of region information */
+int find_reg_hash_idx(gd_region *reg)
+{
+ gd_region *regl;
+ int index;
+
+ for (index = gd_header->n_regions-1, regl = gd_header->regions + index; reg != regl; regl--, index--)
+ assertpro(0 <= index);
+ return index;
+}
diff --git a/sr_unix/fork_init.h b/sr_unix/fork_init.h
index d14a369..9c75a0a 100644
--- a/sr_unix/fork_init.h
+++ b/sr_unix/fork_init.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2011, 2013 Fidelity Information Services, Inc.*
+ * Copyright 2011, 2014 Fidelity Information Services, Inc.*
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,26 +14,22 @@
#include "have_crit.h"
-/* This macro takes care of safely clearing the timer queue and resetting the
- * timer-related globals when we need to fork-off a process. Please note that
- * it is unnecessary to use this macro when the fork is immediately followed
- * by an exec (of any flavor), because the globals would get cleared
- * automatically in that case. To avoid warning messages from ftpput.csh in such
- * situations, append BYPASSOK comment directives to the lines with fork
- * instances.
+/* This macro takes care of safely clearing the timer queue and resetting the timer-related globals when we need
+ * to fork-off a process. Note that it is necessary to use this macro EVEN WHEN the fork is immediately followed
+ * by an exec (of any flavor), because of the ENABLE_INTERRUPTS macro usage right after the "fork" call.
+ * If this call is done in the child process (0 == pid), and timer variables are not cleared, it is possible
+ * (if the right conditions are met) that "have_crit" gets invoked as part of the ENABLE_INTERRUPTS macro in
+ * the child process and ends up with a GTMASSERT -- BYPASSOK -- (GTM-8050). If timers have not been initialized at all,
+ * then "clear_timers" does no system calls so the only overhead is a function call invocation which is okay considering
+ * we anyways have invoked the "fork()" system call just now.
*/
-#define FORK_CLEAN(pid) \
-{ \
- FORK(pid); \
- if (0 == pid) \
- clear_timers(); \
-}
-
-#define FORK(pid) \
-{ \
+#define FORK(pid) \
+{ \
DEFER_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM) \
- pid = fork(); \
+ pid = fork(); \
+ if (0 == pid) \
+ clear_timers(); \
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM) \
}
diff --git a/sr_unix/ftok.c b/sr_unix/ftok.c
index 97f74f5..6ec3aa0 100644
--- a/sr_unix/ftok.c
+++ b/sr_unix/ftok.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -66,6 +66,6 @@ int main (int argc, char *argv[])
{
PRINTF("%20s :: %d [ 0x%x ]\n", argv[i], FTOK(argv[i], id), FTOK(argv[i], id));
}
-
PRINTF("\n");
+ return 0;
}
diff --git a/sr_unix/gdeverif.m b/sr_unix/gdeverif.m
index f47567b..60a8bbb 100644
--- a/sr_unix/gdeverif.m
+++ b/sr_unix/gdeverif.m
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2006, 2013 Fidelity Information Services, Inc ;
+; Copyright 2006, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -162,6 +162,7 @@ key2blk:
; the computation below allows for at least 1 max-key record in a data OR index block.
; since an index block always contains a *-key, we need to account for that too.
; bs:block size, y:supportable max key size, f:size of reserved bytes, ks:key size
+ i REGION="TEMPLATE" q ; do not do keysize/blksize check for TEMPLATE region as this is not a real region
s y=bs-f-SIZEOF("blk_hdr")-len("min_val")-SIZEOF("rec_hdr")-len("hide_subs")-len("bstar_rec")
i ks>y s verified=0 zm gdeerr("KEYSIZIS"):ks,gdeerr("KEYFORBLK"):bs:f:y,gdeerr("REGIS"):REGION
q
diff --git a/sr_unix/gds_rundown.c b/sr_unix/gds_rundown.c
index cafd7d9..ae77957 100644
--- a/sr_unix/gds_rundown.c
+++ b/sr_unix/gds_rundown.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -145,6 +145,7 @@ int4 gds_rundown(void)
boolean_t was_crit;
boolean_t safe_mode; /* Do not flush or take down shared memory. */
boolean_t bypassed_ftok = FALSE, bypassed_access = FALSE, may_bypass_ftok, inst_is_frozen;
+ int secshrstat;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -183,9 +184,9 @@ int4 gds_rundown(void)
ESTABLISH_NORET(gds_rundown_ch, err_caught);
if (err_caught)
{
+ REVERT;
gds_rundown_err_cleanup(have_standalone_access);
ENABLE_INTERRUPTS(INTRPT_IN_GDS_RUNDOWN);
- REVERT;
DEBUG_ONLY(ok_to_UNWIND_in_exit_handling = FALSE);
return EXIT_ERR;
}
@@ -511,18 +512,15 @@ int4 gds_rundown(void)
{ /* If we_are_last_writer, we would have already done a wcs_flu() which would
* have written an epoch record and we are guaranteed no further updates
* since we are the last writer. So, just close the journal.
- * Although we assert pini_addr should be non-zero for last_writer, we
- * play it safe in PRO and write a PINI record if not written already.
+ * If the freeaddr == post_epoch_freeaddr, wcs_flu may have skipped writing
+ * a pini, so allow for that.
*/
assert(!jbp->before_images || is_mm
- || !we_are_last_writer || (0 != jpc->pini_addr || jgbl.mur_extract));
- if (!jgbl.mur_extract)
- {
- if (we_are_last_writer && 0 == jpc->pini_addr)
- jnl_put_jrt_pini(csa);
- if (0 != jpc->pini_addr)
- jnl_put_jrt_pfin(csa);
- }
+ || !we_are_last_writer || (0 != jpc->pini_addr) || jgbl.mur_extract
+ || (jpc->jnl_buff->freeaddr == jpc->jnl_buff->post_epoch_freeaddr));
+ /* If we haven't written a pini, let jnl_file_close write the pini/pfin. */
+ if (!jgbl.mur_extract && (0 != jpc->pini_addr))
+ jnl_put_jrt_pfin(csa);
/* If not the last writer and no pending flush timer left, do jnl flush now */
if (!we_are_last_writer && (0 > csa->nl->wcs_timers))
{
@@ -608,9 +606,13 @@ int4 gds_rundown(void)
db_ipcs.fn[reg->dyn.addr->fname_len] = 0;
/* request gtmsecshr to flush. read_only cannot flush itself */
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa);
- if (0 != send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0))
- rts_error_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg),
- ERR_TEXT, 2, RTS_ERROR_TEXT("gtmsecshr failed to update database file header"));
+ if (!csa->read_only_fs)
+ {
+ secshrstat = send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0);
+ if (0 != secshrstat)
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg),
+ ERR_TEXT, 2, RTS_ERROR_TEXT("gtmsecshr failed to update database file header"));
+ }
}
/* Done with file now, close it */
CLOSEFILE_RESET(udi->fd, rc); /* resets "udi->fd" to FD_INVALID */
@@ -671,6 +673,8 @@ int4 gds_rundown(void)
if (0 != shm_rmid(udi->shmid))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg),
ERR_TEXT, 2, RTS_ERROR_TEXT("Unable to remove shared memory"));
+ /* Note that we no longer have a new shared memory. Currently only used/usable for standalone rollback. */
+ udi->new_shm = FALSE;
/* mupip recover/rollback don't release the semaphore here, but do it later in db_ipcs_reset (invoked from
* mur_close_files())
*/
@@ -679,6 +683,7 @@ int4 gds_rundown(void)
if (0 != sem_rmid(udi->semid))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg),
ERR_TEXT, 2, RTS_ERROR_TEXT("Unable to remove semaphore"));
+ udi->new_sem = FALSE; /* Note that we no longer have a new semaphore */
udi->grabbed_access_sem = FALSE;
udi->counter_acc_incremented = FALSE;
}
diff --git a/sr_unix/gds_rundown_ch.c b/sr_unix/gds_rundown_ch.c
index d05f2c9..974e640 100644
--- a/sr_unix/gds_rundown_ch.c
+++ b/sr_unix/gds_rundown_ch.c
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2013 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#include "mdef.h"
#include "error.h"
diff --git a/sr_unix/gds_rundown_err_cleanup.c b/sr_unix/gds_rundown_err_cleanup.c
index a25ba36..38b2f86 100644
--- a/sr_unix/gds_rundown_err_cleanup.c
+++ b/sr_unix/gds_rundown_err_cleanup.c
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2013 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#include "mdef.h"
#include "gdsroot.h"
#include "gtm_facility.h"
diff --git a/sr_unix/gds_rundown_err_cleanup.h b/sr_unix/gds_rundown_err_cleanup.h
index 14759cd..6248c93 100644
--- a/sr_unix/gds_rundown_err_cleanup.h
+++ b/sr_unix/gds_rundown_err_cleanup.h
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2013 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#ifndef GDS_RUNDOWN_ERR_CLEANUP_INCLUDED
#define GDS_RUNDOWN_ERR_CLEANUP_INCLUDED
diff --git a/sr_unix/gen_sym_key.sh b/sr_unix/gen_sym_key.sh
index 3ca96f0..591f4e5 100644
--- a/sr_unix/gen_sym_key.sh
+++ b/sr_unix/gen_sym_key.sh
@@ -1,7 +1,7 @@
#!/bin/sh
#################################################################
# #
-# Copyright 2010 Fidelity Information Services, Inc #
+# Copyright 2010, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -77,5 +77,9 @@ comment="$*" ; if [ -z "$comment" ] ; then comment="Key in $output_file created
dir_path=`dirname $0` ; if [ -z "$dir_path" ] ; then dir_path=$PWD ; fi
+# If $gtm_encrypt_notty is defined, we want to use it.
+notty=$gtm_encrypt_notty
+
# Generate random key and save the output encrypted and signed
-$gpg --gen-random $random_strength $SYM_KEY_LEN | $gpg --armor --encrypt --default-recipient-self --comment "$comment" --output $output_file
+$gpg $notty --gen-random $random_strength $SYM_KEY_LEN | \
+ $gpg --armor --encrypt --default-recipient-self --comment "$comment" --output $output_file $notty
diff --git a/sr_unix/gen_xfer_desc.csh b/sr_unix/gen_xfer_desc.csh
index 58c6e37..91afb53 100644
--- a/sr_unix/gen_xfer_desc.csh
+++ b/sr_unix/gen_xfer_desc.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2008, 2011 Fidelity Information Services, Inc #
+# Copyright 2008, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -93,6 +93,7 @@ cat << TEST >! temp_xyz_ia.c
/* We have not yet created gtm_threadgbl_deftypes.h and don't need it, signal gtm_threadgbl.h to avoid including it */
#define NO_THREADGBL_DEFTYPES
#include "mdef.h"
+#include "xfer_enum.h"
#define XFER(a,b) MY_XF,b
#include "xfer.h"
TEST
diff --git a/sr_unix/generic_signal_handler.c b/sr_unix/generic_signal_handler.c
index a5266cf..82f65d3 100644
--- a/sr_unix/generic_signal_handler.c
+++ b/sr_unix/generic_signal_handler.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -131,7 +131,7 @@ void generic_signal_handler(int sig, siginfo_t *info, void *context)
}
++core_in_progress;
DUMP_CORE;
- GTMASSERT;
+ assertpro(!((SIGSEGV == sig) || (SIGBUS == sig) || (SIGKILL == sig)));
default:
;
}
@@ -191,7 +191,7 @@ void generic_signal_handler(int sig, siginfo_t *info, void *context)
break;
default:
exit_state = EXIT_IMMED;
- GTMASSERT;
+ assertpro(FALSE && signal_info.infotype); /* show signal_info if there's a failure */
}
/* If nothing pending AND we have crit or already in exit processing, wait to invoke shutdown */
if (DEFER_EXIT_PROCESSING)
@@ -293,7 +293,7 @@ void generic_signal_handler(int sig, siginfo_t *info, void *context)
default:
exit_state = EXIT_IMMED;
SET_PROCESS_EXITING_TRUE;
- GTMASSERT;
+ assertpro(FALSE && signal_info.infotype);; /* show signal_info if there's a failure */
}
if (0 != signal_info.sig_err)
{
diff --git a/sr_unix/get_lib_dirs.mk b/sr_unix/get_lib_dirs.mk
deleted file mode 100644
index b17f1ec..0000000
--- a/sr_unix/get_lib_dirs.mk
+++ /dev/null
@@ -1,151 +0,0 @@
-#################################################################
-# #
-# Copyright 2002, 2011 Fidelity Information Services, Inc #
-# #
-# This source code contains the intellectual property #
-# of its copyright holder(s), and is made available #
-# under a license. If you do not know the terms of #
-# the license, please stop and do not read further. #
-# #
-#################################################################
-############### Define platform-specific directory ring-down ##################################
-# The purpose of this file is to define the source directories
-# for each platform
-# It also defines
-# - gt_build_type <--- significance for 32bit Linux
-# - gt_use_nsb <--- 32bit Linux and CYGWIN use NSB
-# - gt_build_xfer_desc <- ia64/x86_64 Linuxen and HPUX IA64 use this
-
-# Preserve sanity ###############################################
-# 32bit Linux/CYGWIN are the only GT.M builds that use
-# non-shared binaries, aka nsb. 32bit Linux builds are
-# the most error prone since x86 starts at i386 till i686
-# and you can build 32bit on x86_64 by setting OBJECT_MODE
-# to 32
-# We must do these checks first to ID NSB builds and 32bit
-# linux builds which throw a monkey wrench into the whole
-# process.
-
-##################################
-# gt_machine_type set in comlist.mk to $(shell uname -m)
-# gt_os_type set in comlist.mk to $(shell uname -s)
-
-# only HPUX ia64 and Linux ia64/x86_64 need this option
-# optimize for not using it
-gt_build_xfer_desc=0
-
-# default to using shared libraries
-gt_use_nsb=0
-
-# Sanitize the CYGWIN gt_os_type and mark it as NSB
-ifeq ($(findstring CYGWIN,$(gt_os_type)), CYGWIN)
-$(info Cygwin Host)
-gt_os_type=CYGWIN
-gt_use_nsb=1
-endif
-
-# BEGIN Linux host, check for 32 bitness
-gt_build_type=0
-ifeq ($(gt_os_type), Linux)
-gt_build_type=64
-
-ifeq ($(gt_machine_type),i386)
-gt_use_nsb=1
-gt_build_type=32
-endif
-
-ifeq ($(gt_machine_type),i686)
-gt_use_nsb=1
-gt_build_type=32
-endif
-
-ifeq ($(OBJECT_MODE),32)
-gt_use_nsb=1
-gt_build_type=32
-# Checking for OBJECT_MODE 32 is not accurate
-# throw an error if the ARCH is not x86_64
-ifneq ($(gt_machine_type),x86_64)
-$(error OBJECT_MODE set to 32, but arch is $(gt_machine_type)))
-endif
-endif
-
-$(info Linux Host $(gt_build_type))
-endif
-# END Linux host, check for 32 bitness
-
-
-# BEGIN common dirs, optimized for shared libs
-common_dirs_sp=unix_gnp unix_cm unix port_cm port
-ifeq ($(gt_use_nsb), 1)
-common_dirs_sp=unix_gnp unix_cm unix_nsb unix port_cm port
-endif
-# END common dirs, optimized for shared libs
-
-
-# BEGIN ARCH dirs
-ifeq ($(gt_os_type), SunOS)
-lib_dirs_sp=sun sparc $(common_dirs_sp)
-endif
-
-ifeq ($(gt_os_type), AIX)
-lib_dirs_sp=aix rs6000 $(common_dirs_sp)
-endif
-
-ifeq ($(gt_os_type), OSF1)
-lib_dirs_sp=dux alpha $(common_dirs_sp)
-endif
-
-ifeq ($(gt_os_type), CYGWIN)
-lib_dirs_sp=linux i386 x86_regs $(common_dirs_sp)
-endif
-
-ifeq ($(gt_os_type), Linux)
-
-## Begin Linux specific cludgery
-### Ugliness due to building 32bit x86 GT.M on x86_64 machines
-ifeq ($(gt_build_type),32)
-linux_arch=linux i386 x86_regs
-else
-linux_arch=linux x86_64 x86_regs
-gt_build_xfer_desc=1
-endif
-
-### WARNING: leave all 64bit Linuxen below this point
-ifeq ($(gt_machine_type),s390x)
-linux_arch=l390 s390 linux
-endif
-ifeq ($(gt_machine_type), ia64)
-linux_arch=linux ia64
-gt_build_xfer_desc=1
-endif
-## now set lib_dirs_sp
-lib_dirs_sp=$(linux_arch) $(common_dirs_sp)
-$(info Linux Host $(linux_arch))
-## End Linux specific cludgery
-endif
-
-ifeq ($(gt_os_type), HP-UX)
-ifeq ($(gt_machine_type),ia64)
-lib_dirs_sp=hpux ia64 $(common_dirs_sp)
-gt_build_xfer_desc=1
-else
-lib_dirs_sp=hpux hppa $(common_dirs_sp)
-endif
-endif
-
-ifeq ($(gt_os_type), OS/390)
-lib_dirs_sp=os390 s390 $(common_dirs_sp)
-endif
-# END Arch
-
-
-# final sources list, prepend sr_
-gt_src_list:=$(addprefix sr_, $(lib_dirs_sp))
-
-## in house. override the above selections
-## dunno what this is for
-ifdef usertype
-gt_src_list:=src inc tools pct
-endif
-
-$(info Source Directory List: $(gt_src_list))
diff --git a/sr_unix/get_src_line.c b/sr_unix/get_src_line.c
index 4be5245..a432a23 100644
--- a/sr_unix/get_src_line.c
+++ b/sr_unix/get_src_line.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -41,14 +41,20 @@
#endif
#include "stack_frame.h"
#include "rtn_src_chksum.h"
+#include "cmd_qlf.h"
#define RT_TBL_SZ 20
+STATICFNDCL boolean_t fill_src_tbl(routine_source **src_tbl_result, rhdtyp *rtn_vector);
+STATICFNDCL boolean_t fill_src_tbl_via_litpool(routine_source **src_tbl_result, rhdtyp *rtn_vector);
+STATICFNDCL boolean_t fill_src_tbl_via_mfile(routine_source **src_tbl_result, rhdtyp *rtn_vector);
+
GBLREF uint4 dollar_tlevel;
GBLREF unsigned int t_tries;
GBLREF stack_frame *frame_pointer;
LITDEF char litconst_space = ' ';
+LITDEF mval literal_null;
error_def(ERR_TXTSRCFMT);
error_def(ERR_SYSCALL);
@@ -122,6 +128,7 @@ int get_src_line(mval *routine, mval *label, int offset, mstr **srcret, boolean_
if (NULL == rtn_vector)
return OBJMODMISS;
}
+ USHBIN_ONLY(rtn_vector = op_rhd_ext(routine, (mval *)&literal_null, rtn_vector, NULL));
}
if (!rtn_vector->src_full_name.len)
return SRCNOTAVAIL;
@@ -189,151 +196,7 @@ int get_src_line(mval *routine, mval *label, int offset, mstr **srcret, boolean_
} else
# endif
{
- srcfile_name = malloc(rtn_vector->src_full_name.len + 1);
- memcpy(srcfile_name, rtn_vector->src_full_name.addr, rtn_vector->src_full_name.len);
- *(srcfile_name + rtn_vector->src_full_name.len) = 0; /* ensure string is null terminated */
- /* At this point, it is not clear if Fopen will handle zos tagging correctly in all cases.
- * especially when tagged with other than ISO8859-1 or IBM-1047. When we resurrect the zOS
- * platform, we need to test this out.
- */
- fp = Fopen(srcfile_name, "r");
- if (NULL == fp)
- {
- free(srcfile_name);
- srcfile_name = NULL;
- srcfilnamlen = (int)rtn_vector->routine_name.len;
- memcpy(srcnamebuf, rtn_vector->routine_name.addr, srcfilnamlen);
- if (srcnamebuf[0] == '%') /* percents are translated to _ on filenames */
- srcnamebuf[0] = '_';
- MEMCPY_LIT(&srcnamebuf[srcfilnamlen], DOTM);
- src.addr = srcnamebuf;
- src.len = INTCAST(srcfilnamlen + STR_LIT_LEN(DOTM));
- zro_search (0, 0, &src, &srcdir, TRUE);
- if (srcdir)
- {
- srcfile_name = malloc(src.len + srcdir->str.len + 2);
- memcpy(srcfile_name, srcdir->str.addr, srcdir->str.len);
- cptr = srcfile_name + srcdir->str.len;
- *cptr++ = '/';
- memcpy(cptr, src.addr, src.len);
- cptr += src.len;
- *cptr++ = 0;
- fp = Fopen(srcfile_name, "r");
- if (NULL == fp)
- {
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) errno);
- assert(FALSE);
- }
- found = TRUE;
- } else
- found = FALSE;
- } else
- found = TRUE;
-
- if (!found)
- {
- srcstat |= SRCNOTFND;
- srcrecs = 0;
- srcsize = 0;
- } else
- {
- srcrecs = (int)rtn_vector->lnrtab_len;
- /* Find out how big the file is so we can allocate the memory in one shot */
- if ((NULL != fp) && !(srcstat & (SRCNOTFND | SRCNOTAVAIL)))
- {
- rc = stat(srcfile_name, &srcfile_stat);
- if (0 != rc)
- {
- free(srcfile_name);
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL,
- 5, LEN_AND_LIT("stat"), CALLFROM, rc);
- }
- srcsize = srcfile_stat.st_size;
- } else
- srcsize = 0;
- }
- if (NULL != srcfile_name)
- free(srcfile_name);
- assert((found && srcrecs >= 1) || (srcrecs == 0));
-
- /* Allocate source mstr structure. Since structure has one mstr in it, allocate one less.
- * Note, the size we get from lnrtab_len has an extra [0] origin entry in the total. This
- * entry is not used in the source array for direct referencing ease.
- */
- src_tbl = (routine_source *)malloc(SIZEOF(routine_source) + ((srcrecs - 1) * SIZEOF(mstr)));
- src_tbl->srcbuff = (0 < srcsize) ? malloc(srcsize) : NULL;
- base = src_tbl->srclines;
- srcptr = src_tbl->srcbuff;
- DEBUG_ONLY(srcptr_max = srcptr + srcsize);
- src_tbl->srcrecs = srcrecs;
- eof_seen = FALSE;
- for (current = base + 1, top = base + srcrecs ; current < top ; current++)
- {
- assert(found && (NULL != fp));
- if (!eof_seen)
- {
- FGETS(buff, MAX_SRCLINE, fp, fgets_rc);
- if (NULL == fgets_rc)
- {
- if (ferror(fp))
- {
- FCLOSE(fp, fclose_res);
- assert(!fclose_res);
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_TXTSRCFMT, 0, errno);
- assert(FALSE);
- } else
- {
- eof_seen = TRUE;
- assert(feof(fp));
- size = 0;
- }
- } else
- {
- size = (int)STRLEN(buff);
- prev_srcptr = srcptr;
- memcpy(srcptr, buff, size);
- srcptr += size;
- /* Strip trailing '\n' if any (if at least one byte was read in) */
- if (size && ('\n' == buff[size - 1]))
- size--;
- }
- } else /* eof seen; nothing more to read in file */
- size = 0;
- if (size)
- {
- assert((prev_srcptr + size) <= srcptr_max);
- current->len = size;
- current->addr = (char *)prev_srcptr;
- } else
- {
- current->addr = (char *)&litconst_space;
- current->len = 1;
- }
- }
- if (found)
- {
- *base = *(base + 1);
- /* Ensure we have reached the end of the source file. If not, we need to issue a CHECKSUMFAIL
- * error. Most often the !eof_seen part of the check is not needed since the checksums will not
- * match. But if it so happens that the checksums do match, then this extra check helps us
- * correctly identify a TXTSRCMAT error.
- */
- if (!eof_seen)
- {
- FGETS(buff, MAX_SRCLINE, fp, fgets_rc);
- if ((NULL == fgets_rc) && !ferror(fp))
- {
- eof_seen = TRUE;
- assert(feof(fp));
- }
- }
- rtn_src_chksum_buffer(&checksum_ctx, src_tbl->srcbuff, srcsize);
- if (!eof_seen
- || !rtn_src_chksum_match(get_ctx_checksum(&checksum_ctx), get_rtnhdr_checksum(rtn_vector)))
- srcstat |= CHECKSUMFAIL;
- FCLOSE(fp, fclose_res);
- assert(!fclose_res);
- }
+ srcstat = fill_src_tbl(&src_tbl, rtn_vector);
}
src_tbl->srcstat = srcstat;
rtn_vector->source_code = src_tbl;
@@ -374,3 +237,223 @@ void free_src_tbl(rhdtyp *rtn_vector)
rtn_vector->source_code = NULL;
}
}
+
+STATICFNDEF boolean_t fill_src_tbl(routine_source **src_tbl_result, rhdtyp *rtn_vector)
+{
+ if (rtn_vector->compiler_qlf & CQ_EMBED_SOURCE)
+ return fill_src_tbl_via_litpool(src_tbl_result, rtn_vector);
+ else
+ return fill_src_tbl_via_mfile(src_tbl_result, rtn_vector);
+}
+
+STATICFNDEF boolean_t fill_src_tbl_via_litpool(routine_source **src_tbl_result, rhdtyp *rtn_vector)
+{
+ int srcrecs, size;
+ mstr *current, *top;
+ routine_source *src_tbl;
+ off_t srcsize;
+ unsigned char *srcptr, *srcptr_max, *srcstart, *prev_srcptr;
+
+ srcrecs = (int)rtn_vector->lnrtab_len;
+ /* Each line of source (srcrecs of them) resides at end of lit pool (srcptr) */
+ USHBIN_ONLY(srcptr = rtn_vector->literal_text_adr + rtn_vector->routine_source_offset);
+ USHBIN_ONLY(srcsize = rtn_vector->literal_text_len - rtn_vector->routine_source_offset);
+ NON_USHBIN_ONLY(srcptr = (unsigned char *)rtn_vector->routine_source_offset);
+ NON_USHBIN_ONLY(srcsize = (int)rtn_vector->routine_source_length);
+ srcptr_max = srcptr + srcsize;
+ src_tbl = (routine_source *)malloc(SIZEOF(routine_source) + ((srcrecs - 1) * SIZEOF(mstr)));
+ src_tbl->srcbuff = NULL;
+ src_tbl->srcrecs = srcrecs;
+ for (current = src_tbl->srclines + 1, top = src_tbl->srclines + srcrecs ; current < top ; current++)
+ {
+ prev_srcptr = srcptr++;
+ while ((srcptr < srcptr_max) && (*(srcptr - 1) != '\n')) /* find end of current line */
+ srcptr++;
+ size = (int4)(srcptr - prev_srcptr);
+ if (*(srcptr - 1) == '\n')
+ size--; /* Strip trailing '\n' */
+ if (size)
+ {
+ current->len = size;
+ current->addr = (char *)prev_srcptr;
+ } else
+ {
+ current->len = 1;
+ current->addr = (char *)&litconst_space;
+ }
+ }
+ /* NOTE: no need to verify source checksum. no chance of mismatch */
+ *src_tbl_result = src_tbl;
+ return 0;
+}
+
+STATICFNDEF boolean_t fill_src_tbl_via_mfile(routine_source **src_tbl_result, rhdtyp *rtn_vector)
+{
+ int srcrecs, *lt_ptr, size, line_indx, srcfilnamlen;
+ boolean_t found, added, eof_seen, srcstat;
+ mstr src;
+ zro_ent *srcdir;
+ mstr *base, *current, *top;
+ char buff[MAX_SRCLINE], *cptr, *srcfile_name;
+ char srcnamebuf[SIZEOF(mident_fixed) + STR_LIT_LEN(DOTM)];
+ routine_source *src_tbl;
+ int rc, fclose_res;
+ char *fgets_rc;
+ FILE *fp;
+ struct stat srcfile_stat;
+ off_t srcsize;
+ unsigned char *srcptr, *srcptr_max, *srcstart, *eol_srcstart, *prev_srcptr;
+ gtm_rtn_src_chksum_ctx checksum_ctx;
+
+ srcstat = 0;
+ srcfile_name = malloc(rtn_vector->src_full_name.len + 1);
+ memcpy(srcfile_name, rtn_vector->src_full_name.addr, rtn_vector->src_full_name.len);
+ *(srcfile_name + rtn_vector->src_full_name.len) = 0; /* ensure string is null terminated */
+ /* At this point, it is not clear if Fopen will handle zos tagging correctly in all cases.
+ * especially when tagged with other than ISO8859-1 or IBM-1047. When we resurrect the zOS
+ * platform, we need to test this out.
+ */
+ fp = Fopen(srcfile_name, "r");
+ if (NULL == fp)
+ {
+ free(srcfile_name);
+ srcfile_name = NULL;
+ srcfilnamlen = (int)rtn_vector->routine_name.len;
+ memcpy(srcnamebuf, rtn_vector->routine_name.addr, srcfilnamlen);
+ if (srcnamebuf[0] == '%') /* percents are translated to _ on filenames */
+ srcnamebuf[0] = '_';
+ MEMCPY_LIT(&srcnamebuf[srcfilnamlen], DOTM);
+ src.addr = srcnamebuf;
+ src.len = INTCAST(srcfilnamlen + STR_LIT_LEN(DOTM));
+ zro_search (0, 0, &src, &srcdir, TRUE);
+ if (srcdir)
+ {
+ srcfile_name = malloc(src.len + srcdir->str.len + 2);
+ memcpy(srcfile_name, srcdir->str.addr, srcdir->str.len);
+ cptr = srcfile_name + srcdir->str.len;
+ *cptr++ = '/';
+ memcpy(cptr, src.addr, src.len);
+ cptr += src.len;
+ *cptr++ = 0;
+ fp = Fopen(srcfile_name, "r");
+ found = (NULL != fp) ? TRUE : FALSE;
+ } else
+ found = FALSE;
+ } else
+ found = TRUE;
+
+ if (!found)
+ {
+ srcstat |= SRCNOTFND;
+ srcrecs = 0;
+ srcsize = 0;
+ } else
+ {
+ srcrecs = (int)rtn_vector->lnrtab_len;
+ /* Find out how big the file is so we can allocate the memory in one shot */
+ if ((NULL != fp) && !(srcstat & (SRCNOTFND | SRCNOTAVAIL)))
+ {
+ rc = stat(srcfile_name, &srcfile_stat);
+ if (0 != rc)
+ {
+ free(srcfile_name);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL,
+ 5, LEN_AND_LIT("stat"), CALLFROM, rc);
+ }
+ srcsize = srcfile_stat.st_size;
+ } else
+ srcsize = 0;
+ }
+ if (NULL != srcfile_name)
+ free(srcfile_name);
+ assert((found && srcrecs >= 1) || (srcrecs == 0));
+
+ /* Allocate source mstr structure. Since structure has one mstr in it, allocate one less.
+ * Note, the size we get from lnrtab_len has an extra [0] origin entry in the total. This
+ * entry is not used in the source array for direct referencing ease.
+ */
+ src_tbl = (routine_source *)malloc(SIZEOF(routine_source) + ((srcrecs - 1) * SIZEOF(mstr)));
+ src_tbl->srcbuff = (0 < srcsize) ? malloc(srcsize) : NULL;
+ base = src_tbl->srclines;
+ srcptr = src_tbl->srcbuff;
+ DEBUG_ONLY(srcptr_max = srcptr + srcsize);
+ src_tbl->srcrecs = srcrecs;
+ eof_seen = FALSE;
+ for (current = base + 1, top = base + srcrecs ; current < top ; current++)
+ {
+ assert(found && (NULL != fp));
+ if (!eof_seen)
+ {
+ FGETS(buff, MAX_SRCLINE, fp, fgets_rc);
+ if (NULL == fgets_rc)
+ {
+ if (ferror(fp))
+ {
+ FCLOSE(fp, fclose_res);
+ assert(!fclose_res);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_TXTSRCFMT, 0, errno);
+ assert(FALSE);
+ } else
+ {
+ eof_seen = TRUE;
+ assert(feof(fp));
+ size = 0;
+ }
+ } else
+ {
+ size = (int)STRLEN(buff);
+ prev_srcptr = srcptr;
+ srcptr += size;
+ if (srcptr > (src_tbl->srcbuff + srcsize))
+ { /* source file has been concurrently overwritten (and extended) */
+ srcstat |= CHECKSUMFAIL;
+ eof_seen = TRUE;
+ size = 0;
+ } else
+ {
+ memcpy(prev_srcptr, buff, size);
+ /* Strip trailing '\n' if any (if at least one byte was read in) */
+ if (size && ('\n' == buff[size - 1]))
+ size--;
+ }
+ }
+ } else /* eof seen; nothing more to read in file */
+ size = 0;
+ if (size)
+ {
+ assert((prev_srcptr + size) <= srcptr_max);
+ current->len = size;
+ current->addr = (char *)prev_srcptr;
+ } else
+ {
+ current->addr = (char *)&litconst_space;
+ current->len = 1;
+ }
+ }
+ if (found)
+ {
+ *base = *(base + 1);
+ /* Ensure we have reached the end of the source file. If not, we need to issue a CHECKSUMFAIL
+ * error. Most often the !eof_seen part of the check is not needed since the checksums will not
+ * match. But if it so happens that the checksums do match, then this extra check helps us
+ * correctly identify a TXTSRCMAT error.
+ */
+ if (!eof_seen)
+ {
+ FGETS(buff, MAX_SRCLINE, fp, fgets_rc);
+ if ((NULL == fgets_rc) && !ferror(fp))
+ {
+ eof_seen = TRUE;
+ assert(feof(fp));
+ }
+ }
+ rtn_src_chksum_buffer(&checksum_ctx, src_tbl->srcbuff, srcsize);
+ if (!eof_seen
+ || !rtn_src_chksum_match(get_ctx_checksum(&checksum_ctx), get_rtnhdr_checksum(rtn_vector)))
+ srcstat |= CHECKSUMFAIL;
+ FCLOSE(fp, fclose_res);
+ assert(!fclose_res);
+ }
+ *src_tbl_result = src_tbl;
+ return srcstat;
+}
diff --git a/sr_unix/getcaps.c b/sr_unix/getcaps.c
index 3c93f8d..29bd82e 100644
--- a/sr_unix/getcaps.c
+++ b/sr_unix/getcaps.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -69,24 +69,24 @@ GBLDEF int GTM_LINES; /* number of rows */
#pragma convlit(suspend)
#endif
static int gtm_auto_right_margin = 0;
-static char gtm_clr_eos[] = "[J";
-static char gtm_clr_eol[] = "[K";
+static char gtm_clr_eos[] = "\033[J";
+static char gtm_clr_eol[] = "\033[K";
static int gtm_columns = 80;
-static char gtm_cursor_address[] = "[%i%p1%d;%p2%dH";
-static char gtm_cursor_down[] = "\015"; /* <Ctrl-M> */
-static char gtm_cursor_left[] = "";
-static char gtm_cursor_right[] = "OC";
-static char gtm_cursor_up[] = "OA";
+static char gtm_cursor_address[] = "\033[%i%p1%d;%p2%dH";
+static char gtm_cursor_down[] = "\012"; /* <Ctrl-J> */
+static char gtm_cursor_left[] = "\010";
+static char gtm_cursor_right[] = "\033[C";
+static char gtm_cursor_up[] = "\033[A";
static int gtm_eat_newline_glitch = 1;
-static char gtm_key_backspace[] = "";
-static char gtm_key_dc[] = "";
-static char gtm_key_down[] = "OB";
-static char gtm_key_left[] = "OD";
-static char gtm_key_right[] = "OC";
-static char gtm_key_up[] = "OA";
+static char gtm_key_backspace[] = "\010";
+static char gtm_key_dc[] = "\033[3~";
+static char gtm_key_down[] = "\033OB";
+static char gtm_key_left[] = "\033OD";
+static char gtm_key_right[] = "\033OC";
+static char gtm_key_up[] = "\033OA";
static char gtm_key_insert[] = "";
-static char gtm_keypad_local[] = "[?1l";
-static char gtm_keypad_xmit[] = "[?1h";
+static char gtm_keypad_local[] = "\033[?1l";
+static char gtm_keypad_xmit[] = "\033[?1h";
static int gtm_lines = 24;
#if defined(__MVS__) && __CHARSET_LIB==1 /* -qascii */
@@ -118,12 +118,12 @@ static char gtm_cap_ascii[16 * 16]; /* ESC_LEN from io.h times number of tigetst
int getcaps(int fildes)
{
- char *cap;
+ char *cap;
#if defined(__MVS__) && __CHARSET_LIB==1 /* -qascii */
- char cap_ebcdic[128]; /* more than enough for terminal name */
- int ebc_len, gtm_cap_index = 0;
+ char cap_ebcdic[128]; /* more than enough for terminal name */
+ int ebc_len, gtm_cap_index = 0;
#endif
- int status;
+ int status;
cap = GETENV("TERM");
if (!cap)
@@ -177,96 +177,41 @@ int getcaps(int fildes)
#ifdef KEEP_zOS_EBCDIC
#pragma convlit(resume)
#endif
-
assert(-1 != AUTO_RIGHT_MARGIN);
- if (0 == AUTO_RIGHT_MARGIN)
- AUTO_RIGHT_MARGIN = gtm_auto_right_margin;
assert((char *)-1 != CLR_EOS);
- if (NULL == CLR_EOS || (char *)-1 == CLR_EOS)
- CLR_EOS = gtm_clr_eos;
- else
- CAP2ASCII(CLR_EOS);
+ CAP2ASCII(CLR_EOS);
assert((char *)-1 != CLR_EOL);
- if (NULL == CLR_EOL || (char *)-1 == CLR_EOL)
- CLR_EOL = gtm_clr_eol;
- else
- CAP2ASCII(CLR_EOL);
+ CAP2ASCII(CLR_EOL);
assert(-2 != COLUMNS);
- if (-1 == COLUMNS)
- COLUMNS = gtm_columns;
assert((char *)-1 != CURSOR_ADDRESS);
- if (NULL == CURSOR_ADDRESS || (char *)-1 == CURSOR_ADDRESS)
- CURSOR_ADDRESS = gtm_cursor_address;
- else
- CAP2ASCII(CURSOR_ADDRESS);
+ CAP2ASCII(CURSOR_ADDRESS);
assert((char *)-1 != CURSOR_DOWN);
- if (NULL == CURSOR_DOWN || (char *)-1 == CURSOR_DOWN)
- CURSOR_DOWN = gtm_cursor_down;
- else
- CAP2ASCII(CURSOR_DOWN);
+ CAP2ASCII(CURSOR_DOWN);
assert((char *)-1 != CURSOR_LEFT);
- if (NULL == CURSOR_LEFT || (char *)-1 == CURSOR_LEFT)
- CURSOR_LEFT = gtm_cursor_left;
- else
- CAP2ASCII(CURSOR_LEFT);
+ CAP2ASCII(CURSOR_LEFT);
assert((char *)-1 != CURSOR_RIGHT);
- if (NULL == CURSOR_RIGHT || (char *)-1 == CURSOR_RIGHT)
- CURSOR_RIGHT = gtm_cursor_right;
- else
- CAP2ASCII(CURSOR_RIGHT);
+ CAP2ASCII(CURSOR_RIGHT);
assert((char *)-1 != CURSOR_UP);
- if (NULL == CURSOR_UP || (char *)-1 == CURSOR_UP)
- CURSOR_UP = gtm_cursor_up;
- else
- CAP2ASCII(CURSOR_UP);
+ CAP2ASCII(CURSOR_UP);
assert((char *)-1 != KEY_BACKSPACE);
- if (NULL == KEY_BACKSPACE || (char *)-1 == KEY_BACKSPACE)
- KEY_BACKSPACE = gtm_key_backspace;
- else
- CAP2ASCII(KEY_BACKSPACE);
+ CAP2ASCII(KEY_BACKSPACE);
assert((char *)-1 != KEY_DC);
- if (NULL == KEY_DC || (char *)-1 == KEY_DC)
- KEY_DC = gtm_key_dc;
- else
- CAP2ASCII(KEY_DC);
+ CAP2ASCII(KEY_DC);
assert((char *)-1 != KEY_DOWN);
- if (NULL == KEY_DOWN || (char *)-1 == KEY_DOWN)
- KEY_DOWN = gtm_key_down;
- else
- CAP2ASCII(KEY_DOWN);
+ CAP2ASCII(KEY_DOWN);
assert((char *)-1 != KEY_LEFT);
- if (NULL == KEY_LEFT || (char *)-1 == KEY_LEFT)
- KEY_LEFT = gtm_key_left;
- else
- CAP2ASCII(KEY_LEFT);
+ CAP2ASCII(KEY_LEFT);
assert((char *)-1 != KEY_RIGHT);
- if (NULL == KEY_RIGHT || (char *)-1 == KEY_RIGHT)
- KEY_RIGHT = gtm_key_right;
- else
- CAP2ASCII(KEY_RIGHT);
+ CAP2ASCII(KEY_RIGHT);
assert((char *)-1 != KEY_UP);
- if (NULL == KEY_UP || (char *)-1 == KEY_UP)
- KEY_UP = gtm_key_up;
- else
- CAP2ASCII(KEY_UP);
+ CAP2ASCII(KEY_UP);
assert((char *)-1 != KEY_INSERT);
- if (NULL == KEY_INSERT || (char *)-1 == KEY_INSERT)
- KEY_INSERT = gtm_key_insert;
- else
- CAP2ASCII(KEY_INSERT);
+ CAP2ASCII(KEY_INSERT);
assert((char *)-1 != KEYPAD_LOCAL);
- if (NULL == KEYPAD_LOCAL || (char *)-1 == KEYPAD_LOCAL)
- KEYPAD_LOCAL = gtm_keypad_local;
- else
- CAP2ASCII(KEYPAD_LOCAL);
+ CAP2ASCII(KEYPAD_LOCAL);
assert((char *)-1 != KEYPAD_XMIT);
- if (NULL == KEYPAD_XMIT || (char *)-1 == KEYPAD_XMIT)
- KEYPAD_XMIT = gtm_keypad_xmit;
- else
- CAP2ASCII(KEYPAD_XMIT);
+ CAP2ASCII(KEYPAD_XMIT);
assert(-2 != GTM_LINES);
- if (-1 == GTM_LINES)
- GTM_LINES = gtm_lines;
}
else
{
diff --git a/sr_unix/geteuid.c b/sr_unix/geteuid.c
index b626a44..e670cc5 100644
--- a/sr_unix/geteuid.c
+++ b/sr_unix/geteuid.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,8 +16,9 @@
int main(int argc, char **argv)
{
-if (geteuid() == 0)
- PRINTF("root\n");
-else
- PRINTF("other\n");
+ if (geteuid() == 0)
+ PRINTF("root\n");
+ else
+ PRINTF("other\n");
+ return 0;
}
diff --git a/sr_unix/go_load.c b/sr_unix/go_load.c
index d72e8e8..64fb2f6 100644
--- a/sr_unix/go_load.c
+++ b/sr_unix/go_load.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -38,6 +38,7 @@
#include "gtm_utf8.h"
#include <rtnhdr.h>
#include "gv_trigger.h"
+#include "mu_interactive.h"
GBLREF bool mupip_error_occurred;
GBLREF bool mu_ctrly_occurred;
@@ -45,6 +46,7 @@ GBLREF bool mu_ctrlc_occurred;
GBLREF spdesc stringpool;
GBLREF gv_key *gv_currkey;
GBLREF sgmnt_addrs *cs_addrs;
+GBLREF int onerror;
error_def(ERR_LOADCTRLY);
error_def(ERR_LOADEOF);
@@ -52,6 +54,7 @@ error_def(ERR_LOADFILERR);
error_def(ERR_LOADINVCHSET);
error_def(ERR_MUNOFINISH);
error_def(ERR_TRIGDATAIGNORE);
+error_def(ERR_RECLOAD);
#define GO_PUT_SUB 0
#define GO_PUT_DATA 1
@@ -150,6 +153,8 @@ void go_load(uint4 begin, uint4 end)
{
if (++iter > end)
break;
+ if (mupip_error_occurred && ONERROR_STOP == onerror)
+ break;
if (mu_ctrly_occurred)
break;
if (mu_ctrlc_occurred)
@@ -199,10 +204,11 @@ void go_load(uint4 begin, uint4 end)
go_call_db(GO_PUT_SUB, ptr, keylength, 0, 0);
if (mupip_error_occurred)
{
- mu_gvis();
- util_out_print("Error loading record number: !UL\n", TRUE, iter);
- mupip_error_occurred = FALSE;
- continue;
+ mu_gvis();
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_RECLOAD, 1, iter);
+ gv_target = NULL;
+ gv_currkey->base[0] = '\0';
+ ONERROR_PROCESS;
}
assert(keylength < len - 1);
if (max_subsc_len < (gv_currkey->end + 1))
@@ -229,10 +235,9 @@ void go_load(uint4 begin, uint4 end)
: go_call_db(GO_PUT_DATA, (char *)rec_buff, des.len, 0, 0);
if (mupip_error_occurred)
{
- mu_gvis();
- util_out_print("Error loading record number: !UL\n", TRUE, iter);
- mupip_error_occurred = FALSE;
- continue;
+ mu_gvis();
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_RECLOAD, 1, iter);
+ ONERROR_PROCESS;
}
key_count++;
} else
@@ -246,27 +251,28 @@ void go_load(uint4 begin, uint4 end)
hasht_gbl = FALSE;
continue;
}
- go_call_db(GO_PUT_SUB, ptr, len, 0, 0);
+ go_call_db(GO_PUT_SUB, ptr, len, 0, 0);
if (mupip_error_occurred)
{
- mu_gvis();
- util_out_print("Error loading record number: !UL\n", TRUE, iter);
- mupip_error_occurred = FALSE;
- continue;
+ mu_gvis();
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_RECLOAD, 1, iter);
+ gv_target = NULL;
+ gv_currkey->base[0] = '\0';
+ ONERROR_PROCESS;
}
if (max_subsc_len < (gv_currkey->end + 1))
max_subsc_len = gv_currkey->end + 1;
if (++iter > end)
{
- iter--; /* Decrement as didn't load key */
+ iter--; /* Decrement as didn't load key */
break;
}
if ((len = file_input_get(&ptr)) < 0)
break;
if (mupip_error_occurred)
{
- mu_gvis();
- util_out_print("Error loading record number: !UL\n", TRUE, iter);
+ mu_gvis();
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_RECLOAD, 1, iter);
break;
}
stringpool.free = stringpool.base;
@@ -275,10 +281,9 @@ void go_load(uint4 begin, uint4 end)
go_call_db(GO_PUT_DATA, ptr, len, 0, 0);
if (mupip_error_occurred)
{
- mu_gvis();
- util_out_print("Error loading record number: !UL\n", TRUE, iter);
- mupip_error_occurred = FALSE;
- continue;
+ mu_gvis();
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_RECLOAD, 1, iter);
+ ONERROR_PROCESS;
}
key_count++;
}
diff --git a/sr_unix/grab_crit_immediate.c b/sr_unix/grab_crit_immediate.c
index 4fb4d4e..70e7ca2 100644
--- a/sr_unix/grab_crit_immediate.c
+++ b/sr_unix/grab_crit_immediate.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,7 +33,9 @@ GBLREF short crash_count;
GBLREF volatile int4 crit_count;
GBLREF uint4 process_id;
GBLREF node_local_ptr_t locknl;
+#ifdef DEBUG
GBLREF boolean_t mupip_jnl_recover;
+#endif
error_def(ERR_CRITRESET);
error_def(ERR_DBCCERR);
@@ -47,7 +49,9 @@ boolean_t grab_crit_immediate(gd_region *reg)
node_local_ptr_t cnl;
enum cdb_sc status;
mutex_spin_parms_ptr_t mutex_spin_parms;
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
udi = FILE_INFO(reg);
csa = &udi->s_addrs;
csd = csa->hdr;
@@ -68,11 +72,15 @@ boolean_t grab_crit_immediate(gd_region *reg)
case cdb_sc_nolock:
return(FALSE);
case cdb_sc_critreset:
- rts_error(VARLSTCNT(4) ERR_CRITRESET, 2, REG_LEN_STR(reg));
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_CRITRESET, 2, REG_LEN_STR(reg));
case cdb_sc_dbccerr:
- rts_error(VARLSTCNT(4) ERR_DBCCERR, 2, REG_LEN_STR(reg));
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DBCCERR, 2, REG_LEN_STR(reg));
default:
- GTMASSERT;
+ /* An out-of-design return value. assertpro(FALSE) but spell out the failing condition
+ * details instead of just FALSE. Hence the complex structure below.
+ */
+ assertpro((cdb_sc_nolock != status) && (cdb_sc_critreset != status)
+ && (cdb_sc_dbccerr != status) && FALSE);
}
return(FALSE);
}
@@ -88,13 +96,15 @@ boolean_t grab_crit_immediate(gd_region *reg)
}
else
assert(FALSE);
- if (csd->file_corrupt && !mupip_jnl_recover)
- {
- if (!IS_DSE_IMAGE)
- rts_error(VARLSTCNT(4) ERR_DBFLCORRP, 2, DB_LEN_STR(reg));
- else
- gtm_putmsg(VARLSTCNT(4) MAKE_MSG_WARNING(ERR_DBFLCORRP), 2, DB_LEN_STR(reg));
- }
+ /* Commands/Utilties that plays with the file_corrupt flags (DSE/MUPIP SET -PARTIAL_RECOV_BYPASS/RECOVER/ROLLBACK) should
+ * NOT issue DBFLCORRP. Use skip_file_corrupt_check global variable for this purpose. Ideally we need this check only
+ * in grab_crit.c and not grab_crit_immediate.c as all the above commands/utilities only go to grab_crit and do not come
+ * here but we keep it the same for consistency.
+ */
+ /* Assert that MUPIP RECOVER/ROLLBACK has TREF(skip_file_corrupt_check)=TRUE and so does not issue DBFLCORRP error */
+ assert(!mupip_jnl_recover || TREF(skip_file_corrupt_check));
+ if (csd->file_corrupt && !TREF(skip_file_corrupt_check))
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DBFLCORRP, 2, DB_LEN_STR(reg));
/* Ideally we do not want to do wcs_recover if we are in interrupt code (as opposed to mainline code).
* This is easily accomplished in VMS with a library function lib$ast_in_prog but in Unix there is no way
* to tell mainline code from interrupt code without the caller providing that information. Hence we
diff --git a/sr_unix/grab_lock.c b/sr_unix/grab_lock.c
index 22b8dba..a960881 100644
--- a/sr_unix/grab_lock.c
+++ b/sr_unix/grab_lock.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -84,13 +84,13 @@ boolean_t grab_lock(gd_region *reg, boolean_t is_blocking_wait, uint4 onln_rlbk_
switch(status)
{
case cdb_sc_critreset: /* As of 10/07/98, this return value is not possible */
- rts_error(VARLSTCNT(4) ERR_CRITRESET, 2, REG_LEN_STR(reg));
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CRITRESET, 2, REG_LEN_STR(reg));
case cdb_sc_dbccerr:
- rts_error(VARLSTCNT(4) ERR_DBCCERR, 2, REG_LEN_STR(reg));
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DBCCERR, 2, REG_LEN_STR(reg));
case cdb_sc_nolock:
return FALSE;
default:
- GTMASSERT;
+ assertpro(FALSE && status);
}
return FALSE;
}
@@ -108,8 +108,9 @@ boolean_t grab_lock(gd_region *reg, boolean_t is_blocking_wait, uint4 onln_rlbk_
* command is re-run to bring the journal pool/file and instance file to a consistent state.
*/
SNPRINTF(scndry_msg, OUT_BUFF_SIZE, "Instance file header has file_corrupt field set to TRUE");
- /* No need to do rel_lock before rts_error (mupip_exit_handler will do it for us) */
- rts_error(VARLSTCNT(8) ERR_REPLREQROLLBACK, 2, LEN_AND_STR(udi->fn), ERR_TEXT, 2, LEN_AND_STR(scndry_msg));
+ /* No need to do rel_lock before rts_error (mupip_exit_handler will do it for us) - BYPASSOK rts_error */
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_REPLREQROLLBACK, 2, LEN_AND_STR(udi->fn),
+ ERR_TEXT, 2, LEN_AND_STR(scndry_msg));
}
/* If ASSERT_NO_ONLINE_ROLLBACK, then no concurrent online rollbacks can happen at this point. So, the jnlpool
* should be in in sync. There are two exceptions. If this is GT.CM GNP Server and the last client disconnected, the
@@ -130,7 +131,7 @@ boolean_t grab_lock(gd_region *reg, boolean_t is_blocking_wait, uint4 onln_rlbk_
*/
assert((ASSERT_NO_ONLINE_ROLLBACK != onln_rlbk_action)
|| (csa->onln_rlbk_cycle == jnlpool.jnlpool_ctl->onln_rlbk_cycle) || IS_GTCM_GNP_SERVER_IMAGE
- || (jnlpool_init_needed && ANTICIPATORY_FREEZE_AVAILABLE));
+ || (jnlpool_init_needed && INST_FREEZE_ON_ERROR_POLICY));
if ((HANDLE_CONCUR_ONLINE_ROLLBACK == onln_rlbk_action)
&& (csa->onln_rlbk_cycle != jnlpool.jnlpool_ctl->onln_rlbk_cycle))
{
diff --git a/sr_unix/gt_timers.c b/sr_unix/gt_timers.c
index 9092985..bcbedf8 100644
--- a/sr_unix/gt_timers.c
+++ b/sr_unix/gt_timers.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -254,7 +254,6 @@ void set_blocksig(void)
sigaddset(&block_sigsent, SIGTSTP);
sigaddset(&block_sigsent, SIGCONT);
sigaddset(&block_sigsent, SIGALRM);
-
blocksig_initialized = TRUE; /* note the fact that blockalrm and block_sigsent are initialized */
}
@@ -425,11 +424,12 @@ void start_timer(TID tid,
} else if (wcs_clean_dbsync_fptr == handler)
{ /* Account for known instances of the above function being called from within a deferred zone. */
assert((INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) || (INTRPT_IN_WCS_WTSTART == intrpt_ok_state)
- || (INTRPT_IN_DB_CSH_GETN == intrpt_ok_state));
+ || (INTRPT_IN_GDS_RUNDOWN == intrpt_ok_state) || (INTRPT_IN_DB_CSH_GETN == intrpt_ok_state));
safe_to_add = TRUE;
} else if (wcs_stale_fptr == handler)
{ /* Account for known instances of the above function being called from within a deferred zone. */
- assert((INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) || (INTRPT_IN_DB_CSH_GETN == intrpt_ok_state));
+ assert((INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) || (INTRPT_IN_DB_CSH_GETN == intrpt_ok_state)
+ || (INTRPT_IN_TRIGGER_NOMANS_LAND == intrpt_ok_state));
safe_to_add = TRUE;
} else
{
@@ -510,12 +510,21 @@ void clear_timers(void)
{
sigset_t savemask;
+ if (NULL == timeroot)
+ { /* If no timers have been initialized in this process, take fast path (avoid system call) */
+ assert(FALSE == timer_in_handler);
+ assert(FALSE == timer_active);
+ assert(FALSE == heartbeat_started);
+ assert(FALSE == deferred_timers_check_needed);
+ return;
+ }
sigprocmask(SIG_BLOCK, &blockalrm, &savemask); /* block SIGALRM signal */
while (timeroot)
remove_timer(timeroot->tid);
timer_in_handler = FALSE;
timer_active = FALSE;
heartbeat_started = FALSE;
+ deferred_timers_check_needed = FALSE;
sigprocmask(SIG_SETMASK, &savemask, NULL);
return;
}
@@ -751,8 +760,8 @@ STATICFNDEF void timer_handler(int why)
* code do not affect the error_condition global variable that mainline code was relying on. For example, not doing this
* restore caused the update process (in updproc_ch) to issue a GTMASSERT (GTM-7526). BYPASSOK.
*/
- error_condition = save_error_condition;
- errno = save_errno; /* restore mainline errno by similar reasoning as mainline error_condition */
+ SET_ERROR_CONDITION(save_error_condition); /* restore error_condition & severity */
+ errno = save_errno; /* restore mainline errno by similar reasoning as mainline error_condition */
timer_stack_count--;
}
@@ -917,8 +926,7 @@ void sys_canc_timer()
timer_active = FALSE; /* no timer is active now */
}
-/* Cancel all unsafe timers.
- */
+/* Cancel all unsafe timers. */
void cancel_unsafe_timers(void)
{
ABS_TIME at;
@@ -940,8 +948,8 @@ void cancel_unsafe_timers(void)
}
assert((NULL == timeroot) || (0 < safe_timer_cnt));
if (timeroot)
- { /* If the head of the queue has changed, start the current first timer. */
- if (timeroot != active)
+ { /* If the head of the queue has changed, or the system timer was not running, start the current first timer. */
+ if ((active != timeroot) || (!timer_active))
{
sys_get_curr_time(&at);
start_first_timer(&at);
diff --git a/sr_unix/gtm.c b/sr_unix/gtm.c
index d7b164c..eb70e68 100644
--- a/sr_unix/gtm.c
+++ b/sr_unix/gtm.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -98,10 +98,10 @@ int main (int argc, char **argv, char **envp)
return ERR_GTMDISTUNDEF;
}
dir_len = STRLEN(fptr);
- if (GTM_PATH_MAX <= dir_len + STR_LIT_LEN(GTMSHR_IMAGE_NAME) + 1)
+ if (GTM_DIST_PATH_MAX <= dir_len)
{
- FPRINTF(stderr, "%%GTM-E-DISTPATHMAX, $gtm_dist path is greater than maximum (%lu)\n",
- (unsigned long)(GTM_PATH_MAX - STR_LIT_LEN(GTMSHR_IMAGE_NAME) - 2));
+ FPRINTF(stderr, "%%GTM-E-DISTPATHMAX, $gtm_dist path is greater than maximum (%d)\n",
+ GTM_DIST_PATH_MAX);
return ERR_DISTPATHMAX;
}
memcpy(>mshr_file[0], fptr, dir_len);
diff --git a/sr_unix/gtm_bintim.c b/sr_unix/gtm_bintim.c
index f360afc..5eeaa1f 100644
--- a/sr_unix/gtm_bintim.c
+++ b/sr_unix/gtm_bintim.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -146,8 +146,7 @@ static int getmon(char *month)
"jul", "aug", "sep", "oct", "nov", "dec" };
for (p = month; *p; p++)
- if (ISUPPER_ASCII(*p))
- *p = TOLOWER(*p);
+ *p = TOLOWER(*p);
for (i = 0; i < 12; i++)
if (!strcmp(month,m[i]))
return i;
diff --git a/sr_unix/gtm_c_stack_trace.c b/sr_unix/gtm_c_stack_trace.c
index 83e5203..7584574 100644
--- a/sr_unix/gtm_c_stack_trace.c
+++ b/sr_unix/gtm_c_stack_trace.c
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2012, 2013 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#include "mdef.h"
diff --git a/sr_unix/gtm_c_stack_trace_semop.c b/sr_unix/gtm_c_stack_trace_semop.c
index 1843b12..6f6e464 100644
--- a/sr_unix/gtm_c_stack_trace_semop.c
+++ b/sr_unix/gtm_c_stack_trace_semop.c
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2011, 2012 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2011, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#include "mdef.h"
#include "gtm_ipc.h"
#include <sys/sem.h>
diff --git a/sr_unix/gtm_c_stack_trace_semop.h b/sr_unix/gtm_c_stack_trace_semop.h
index e974934..ad78237 100644
--- a/sr_unix/gtm_c_stack_trace_semop.h
+++ b/sr_unix/gtm_c_stack_trace_semop.h
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2011 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2011, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#ifndef GTM_C_STACK_TRACE_SEMOP_INCLUDED
#define GTM_C_STACK_TRACE_SEMOP_INCLUDED
diff --git a/sr_unix/gtm_cshrc.csh b/sr_unix/gtm_cshrc.csh
index a6f4a7c..501b514 100644
--- a/sr_unix/gtm_cshrc.csh
+++ b/sr_unix/gtm_cshrc.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2011 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -57,31 +57,6 @@ if ( $?gtm_environment_init == "0" ) then
if (! -f $gtm_com/versions.csh ) then
echo "gtm_cshrc-E-noversions, There is no versions.csh in $gtm_com"
endif
-
-
- if (-d $gtm_root/V990) then
- set errmsg = "Development ($gtm_root/V990/tools) and installed ($gtm_com) versions of"
- if ( -f $gtm_com/gtm_cshrc.csh ) then # this test should be unnecessary at this point
- diff {$gtm_com/,$gtm_root/V990/tools/}gtm_cshrc.csh >& /dev/null
- if ( $status != 0 ) then
- echo "gtm_cshrc-W-gtm_cshrc_mismatch, $errmsg gtm_cshrc.csh are different."
- endif
- endif
-
- if ( -f $gtm_com/gtmdef.csh ) then # this test should be unnecessary at this point
- diff {$gtm_com/,$gtm_root/V990/tools/}gtmdef.csh >& /dev/null
- if ( $status != 0 ) then
- echo "gtm_cshrc-W-gtmdef_mismatch, $errmsg gtmdef.csh are different."
- endif
- endif
-
- if ( -f $gtm_com/versions.csh ) then
- diff {$gtm_com/,$gtm_root/V990/tools/}versions.csh >& /dev/null
- if ( $status != 0 ) then
- echo "gtm_cshrc-W-versions_mismatch, $errmsg versions.csh are different."
- endif
- endif
- endif
endif
if ( $gtm_cshrc_first_time == "true" ) then
diff --git a/sr_unix/gtm_env.csh b/sr_unix/gtm_env.csh
index 0c3175a..a32c07c 100644
--- a/sr_unix/gtm_env.csh
+++ b/sr_unix/gtm_env.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2010 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -52,7 +52,6 @@ if ( $?gtm_version_change == "1" ) then
setenv gt_ar_archiver "ar" # name of archiver utility
- setenv gt_ar_gtmrpc_name "" # set to "gtmrpc" to create libgtmrpc.a from libgtmrpc.list
setenv gt_ar_option_create "qlv" # quick, use local directory for temp files, verbose
setenv gt_ar_option_update "rlv" # replace, use local directory for temp files, verbose
setenv gt_ar_option_delete "dlv" # delete, use local directory for temp files, verbose
diff --git a/sr_unix/gtm_env_init_sp.c b/sr_unix/gtm_env_init_sp.c
index 68bae0e..4c236ee 100644
--- a/sr_unix/gtm_env_init_sp.c
+++ b/sr_unix/gtm_env_init_sp.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2004, 2013 Fidelity Information Services, Inc *
+ * Copyright 2004, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,6 +16,8 @@
#endif
#include <errno.h>
#include <sys/sem.h>
+#include <sys/types.h>
+#include "gtm_stat.h"
#include "gtm_string.h"
#include "gtm_strings.h"
#include "gtm_ctype.h"
@@ -47,6 +49,8 @@
#include "replgbl.h"
#include "gtm_semutils.h"
#include "gtmlink.h"
+#include "send_msg.h"
+#include "eintr_wrappers.h"
#ifdef __linux__
#include "hugetlbfs_overrides.h"
#endif
@@ -84,6 +88,8 @@ GBLREF char *gtm_core_file;
GBLREF char *gtm_core_putenv;
GBLREF mval dollar_etrap;
GBLREF mval dollar_ztrap;
+GBLREF boolean_t dmterm_default;
+GBLREF boolean_t ipv4_only; /* If TRUE, only use AF_INET. */
ZOS_ONLY(GBLREF char *gtm_utf8_locale_object;)
ZOS_ONLY(GBLREF boolean_t gtm_tag_utf8_as_ascii;)
GTMTRIG_ONLY(GBLREF mval gtm_trigger_etrap;)
@@ -111,14 +117,17 @@ static readonly unsigned char editing_index[27] =
};
static readonly unsigned char init_break[1] = {'B'};
+error_def(ERR_INVLINKTMPDIR);
+
void gtm_env_init_sp(void)
{ /* Unix only environment initializations */
mstr val, trans;
- int4 status, index, len, hrtbt_cntr_delta;
+ int4 status, index, len, hrtbt_cntr_delta, stat_res;
size_t cwdlen;
boolean_t ret, is_defined;
char buf[MAX_TRANS_NAME_LEN], *token, cwd[GTM_PATH_MAX];
char *cwdptr, *trigger_etrap, *c, *end;
+ struct stat outbuf;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -318,7 +327,7 @@ void gtm_env_init_sp(void)
{ /* Only set $ETRAP if the length is usable (may be NULL) */
dollar_etrap.str.addr = malloc(trans.len + 1); /* +1 for '\0'; This memory is never freed */
memcpy(dollar_etrap.str.addr, trans.addr, trans.len);
- *(dollar_etrap.str.addr + trans.len + 1) = '\0';
+ dollar_etrap.str.addr[trans.len] = '\0';
dollar_etrap.str.len = trans.len;
dollar_etrap.mvtype = MV_STR;
}
@@ -335,9 +344,39 @@ void gtm_env_init_sp(void)
if (SS_NORMAL == (status = TRANS_LOG_NAME(&val, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long)))
{
init_relink_allowed(&trans); /* set TREF(relink_allowed) */
- /*for (c = trans.addr, end = c + trans.len; c < end; c++)
- *c = TOUPPER(*c);*/ /* convert trans (an mstr) to all caps */
}
+# ifdef USHBIN_SUPPORTED
+ /* Set default or supplied value for $gtm_linktmpdir */
+ val.addr = GTM_LINKTMPDIR;
+ val.len = SIZEOF(GTM_LINKTMPDIR) - 1;
+ if (SS_NORMAL != (status = TRANS_LOG_NAME(&val, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long)))
+ { /* Else use default $gtm_tmp value or its default */
+ val.addr = GTM_TMP_ENV;
+ val.len = SIZEOF(GTM_TMP_ENV) - 1;
+ if (SS_NORMAL != (status = TRANS_LOG_NAME(&val, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long)))
+ { /* Nothing for $gtm_tmp either - use DEFAULT_GTM_TMP which is already a string */
+ trans.addr = DEFAULT_GTM_TMP;
+ trans.len = SIZEOF(DEFAULT_GTM_TMP) - 1;
+ }
+ }
+ assert(GTM_PATH_MAX > trans.len);
+ (TREF(gtm_linktmpdir)).addr = malloc(trans.len + 1); /* +1 for '\0'; This memory is never freed */
+ (TREF(gtm_linktmpdir)).len = trans.len;
+ /* For now, we assume that if the environment variable is defined to NULL, anticipatory freeze is NOT in effect */
+ if (0 < trans.len)
+ {
+ memcpy((TREF(gtm_linktmpdir)).addr, trans.addr, trans.len);
+ ((TREF(gtm_linktmpdir)).addr)[trans.len] = '\0';
+ }
+ STAT_FILE((TREF(gtm_linktmpdir)).addr, &outbuf, stat_res);
+ if ((-1 == stat_res) || !S_ISDIR(outbuf.st_mode))
+ { /* Either the directory doesn't exist or the entity is not a directory */
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_INVLINKTMPDIR, 2, (TREF(gtm_linktmpdir)).len,
+ (TREF(gtm_linktmpdir)).addr);
+ (TREF(gtm_linktmpdir)).len = SIZEOF(DEFAULT_GTM_TMP) - 1;
+ (TREF(gtm_linktmpdir)).addr = DEFAULT_GTM_TMP;
+ }
+# endif
# ifdef DEBUG
/* DEBUG-only option to bypass 'easy' methods of things and always use gtmsecshr for IPC cleanups, wakeups, file removal,
* etc. Basically use gtmsecshr for anything where it is an option - helps with testing gtmsecshr for proper operation.
@@ -362,4 +401,12 @@ void gtm_env_init_sp(void)
val.len = SIZEOF(GTMDBGFLAGS_FREQ) - 1;
TREF(gtmdbgflags_freq) = trans_numeric(&val, &is_defined, TRUE);
# endif
+ /* See if gtm_ipv4_only is set */
+ val.addr = GTM_IPV4_ONLY;
+ val.len = SIZEOF(GTM_IPV4_ONLY) - 1;
+ ipv4_only = logical_truth_value(&val, FALSE, NULL);
+ /* See if gtm_dmterm is set */
+ val.addr = GTM_DMTERM;
+ val.len = SIZEOF(GTM_DMTERM) - 1;
+ dmterm_default = logical_truth_value(&val, FALSE, NULL);
}
diff --git a/sr_unix/gtm_exit_handler.c b/sr_unix/gtm_exit_handler.c
index 8cd9f73..adee853 100644
--- a/sr_unix/gtm_exit_handler.c
+++ b/sr_unix/gtm_exit_handler.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -44,6 +44,8 @@
#include "print_exit_stats.h"
#include "invocation_mode.h"
#include "secshr_db_clnup.h"
+#include "gtmcrypt.h"
+#include "relinkctl.h"
GBLREF int4 exi_condition;
GBLREF uint4 dollar_tlevel;
@@ -102,6 +104,7 @@ void gtm_exit_handler(void)
package_ptr->package_clnup_rtn();
fgn_closepak(package_ptr->package_handle, INFO);
}
+ relinkctl_rundown(TRUE);
/* We know of at least one case where the below code would error out. That is if this were a replication external
* filter M program halting out after the other end of the pipe has been closed by the source server. In this case,
* the io_rundown call below would error out and would invoke the lastchance3 condition handler which will do an
@@ -118,6 +121,7 @@ void gtm_exit_handler(void)
} else
io_rundown(NORMAL_RUNDOWN);
DEBUG_ONLY(ok_to_UNWIND_in_exit_handling = FALSE;)
+ GTMCRYPT_CLOSE;
REVERT;
print_exit_stats();
diff --git a/sr_unix/gtm_fork_n_core.c b/sr_unix/gtm_fork_n_core.c
index 268632e..5e46194 100644
--- a/sr_unix/gtm_fork_n_core.c
+++ b/sr_unix/gtm_fork_n_core.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -165,7 +165,7 @@ void gtm_fork_n_core(void)
/* block SIGALRM signal */
sigprocmask(SIG_BLOCK, &blockalrm, &savemask);
- FORK(childid); /* BYPASSOK: we exit immediately, no FORK_CLEAN needed */
+ FORK(childid);
if (childid)
{
if (-1 == childid)
diff --git a/sr_unix/gtm_logicals.h b/sr_unix/gtm_logicals.h
index 830476e..1a01a22 100644
--- a/sr_unix/gtm_logicals.h
+++ b/sr_unix/gtm_logicals.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,7 +11,7 @@
/* gtm_logicals.h - Environment variables used by GT.M. */
/* within each group, the entries are in alpha order of the third column */
-/* -------------------------- Common to Unix and VMS -------------------------- */
+/* -------------------------- Common to UNIX and VMS -------------------------- */
#define GTM_DIST_LOG "$gtm_dist"
@@ -81,7 +81,7 @@
#define ZTRAP_NEW "$gtm_ztrap_new"
#define ZYERROR "$gtm_zyerror"
-/* -------------------------- Unix only -------------------------- */
+/* -------------------------- UNIX only -------------------------- */
/* Database */
#define GTM_TMP_ENV "$gtm_tmp"
@@ -110,10 +110,13 @@
#define GTM_BADCHAR_ENV "$gtm_badchar"
#define GTM_ICU_VERSION "$gtm_icu_version"
+/* [Auto]Relink related */
+#define GTM_LINK "$gtm_link"
+#define GTM_LINKTMPDIR "$gtm_linktmpdir"
+
/* Miscellaneous */
#define GTM_ERROR_ON_JNL_FILE_LOST "$gtm_error_on_jnl_file_lost"
#define GTM_ETRAP "$gtm_etrap"
-#define GTM_LINK "$gtm_link"
#define GTM_LOG_ENV "$gtm_log"
#define GTM_LVNULLSUBS "$gtm_lvnullsubs"
#define GTM_NOCENABLE "$gtm_nocenable"
@@ -126,3 +129,4 @@
#define GTMDBGFLAGS_FREQ "$gtmdbgflags_freq"
#define GTM_MAX_STORALLOC "$gtm_max_storalloc"
#define GTM_IPV4_ONLY "$gtm_ipv4_only"
+#define GTM_DMTERM "$gtm_dmterm"
diff --git a/sr_unix/gtm_main.c b/sr_unix/gtm_main.c
index 0feca08..0893604 100644
--- a/sr_unix/gtm_main.c
+++ b/sr_unix/gtm_main.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,11 +33,9 @@
#include "jobchild_init.h"
#include "cli_parse.h"
#include "invocation_mode.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
#include "gtm_main.h" /* for "gtm_main" prototype */
#include "io.h"
-#include "gt_timer.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
#ifdef UNICODE_SUPPORTED
@@ -55,6 +53,7 @@
GBLREF IN_PARMS *cli_lex_in_ptr;
GBLREF char cli_token_buf[];
GBLREF char cli_err_str[];
+GBLREF boolean_t gtm_dist_ok_to_use;
GBLREF CLI_ENTRY mumps_cmd_ary[];
GBLREF boolean_t skip_dbtriggers;
#if defined (GTM_TRIGGER) && (DEBUG)
@@ -106,12 +105,10 @@ int gtm_main (int argc, char **argv, char **envp)
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- set_blocksig();
gtmenvp = envp;
- gtm_imagetype_init(GTM_IMAGE);
+ gtm_dist_ok_to_use = TRUE;
+ common_startup_init(GTM_IMAGE);
GTMTRIG_DBG_ONLY(ch_at_trigger_init = &mdb_condition_handler);
- gtm_wcswidth_fnptr = gtm_wcswidth;
- gtm_env_init(); /* read in all environment variables */
err_init(stop_image_conditional_core);
UNICODE_ONLY(gtm_strToTitle_ptr = >m_strToTitle);
GTM_ICU_INIT_IF_NEEDED; /* Note: should be invoked after err_init (since it may error out) and before CLI parsing */
@@ -168,7 +165,7 @@ int gtm_main (int argc, char **argv, char **envp)
else if (ERR_CRYPTINIT == gtmcrypt_errno)
gtmcrypt_errno = ERR_CRYPTINIT2;
gtmcrypt_errno = SET_CRYPTERR_MASK(gtmcrypt_errno);
- GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, rts_error, SIZEOF(GTMCRYPT_ERRLIT) - 1, GTMCRYPT_ERRLIT);
+ GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, rts_error, SIZEOF(GTMCRYPT_ERRLIT) - 1, GTMCRYPT_ERRLIT); /* BYPASSOK */
}
}
# ifdef GTM_SOCKET_SSL_SUPPORT
diff --git a/sr_unix/gtm_pipe.c b/sr_unix/gtm_pipe.c
index 6227f7d..4b60bf4 100644
--- a/sr_unix/gtm_pipe.c
+++ b/sr_unix/gtm_pipe.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -52,7 +52,7 @@ int gtm_pipe(char *command, pipe_type pt)
PERROR("pipe : ");
return -2;
}
- FORK(child_pid); /* BYPASSOK: we exit immediately, no FORK_CLEAN needed */
+ FORK(child_pid);
if (-1 == child_pid)
{
PERROR("fork : ");
diff --git a/sr_unix/gtm_putmsg.c b/sr_unix/gtm_putmsg.c
index 1cf9280..c4fd8c9 100644
--- a/sr_unix/gtm_putmsg.c
+++ b/sr_unix/gtm_putmsg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -39,7 +39,7 @@ void gtm_putmsg(int argcnt, ...)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- csa = (ANTICIPATORY_FREEZE_AVAILABLE && jnlpool.jnlpool_ctl) ? REG2CSA(gv_cur_region) : NULL;
+ csa = CUSTOM_ERRORS_LOADED ? REG2CSA(gv_cur_region) : NULL;
VAR_START(var, argcnt);
gtm_putmsg_list(csa, argcnt, var);
va_end(var);
@@ -63,7 +63,7 @@ void gtm_putmsg_noflush(int argcnt, ...)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- csa = (ANTICIPATORY_FREEZE_AVAILABLE && jnlpool.jnlpool_ctl) ? REG2CSA(gv_cur_region) : NULL;
+ csa = CUSTOM_ERRORS_LOADED ? REG2CSA(gv_cur_region) : NULL;
VAR_START(var, argcnt);
gtm_putmsg_list(csa, argcnt, var);
va_end(var);
diff --git a/sr_unix/gtm_startup.c b/sr_unix/gtm_startup.c
index 60d3bcb..0ded3c0 100644
--- a/sr_unix/gtm_startup.c
+++ b/sr_unix/gtm_startup.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -143,10 +143,6 @@ OS_PAGE_SIZE_DECLARE
error_def(ERR_COLLATIONUNDEF);
-#ifdef __sun
-#define PACKAGE_ENV_TYPE "GTMXC_RPC" /* env var to use rpc instead of xcall */
-#endif
-
#define MIN_INDIRECTION_NESTING 32
#define MAX_INDIRECTION_NESTING 256
@@ -202,7 +198,6 @@ void gtm_startup(struct startup_vector *svec)
switch (image_type)
{
case GTM_IMAGE:
- case GTM_SVC_DAL_IMAGE:
assert(is_replicator && run_time);
break;
case MUPIP_IMAGE:
@@ -226,10 +221,6 @@ void gtm_startup(struct startup_vector *svec)
zcall_init();
cmd_qlf.qlf = glb_cmd_qlf.qlf;
cache_init();
-# ifdef __sun
- if (NULL != GETENV(PACKAGE_ENV_TYPE)) /* chose xcall (default) or rpc zcall */
- xfer_table[xf_fnfgncal] = (xfer_entry_t)op_fnfgncal_rpc; /* using RPC */
-# endif
msp -= SIZEOF(stack_frame);
frame_pointer = (stack_frame *)msp;
memset(frame_pointer,0, SIZEOF(stack_frame));
@@ -297,7 +288,7 @@ void gtm_startup(struct startup_vector *svec)
if (!TREF(local_collseq))
{
exi_condition = -ERR_COLLATIONUNDEF;
- gtm_putmsg(VARLSTCNT(3) ERR_COLLATIONUNDEF, 1, lct);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_COLLATIONUNDEF, 1, lct);
exit(exi_condition);
}
} else
diff --git a/sr_unix/gtm_startup_chk.c b/sr_unix/gtm_startup_chk.c
index 6d73477..ebca823 100644
--- a/sr_unix/gtm_startup_chk.c
+++ b/sr_unix/gtm_startup_chk.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -15,15 +15,21 @@
* communication fails, it can cause many problems.
* This is the startup checking including the following:
* gtm_chk_dist()
- * 1. $gtm_dist is defined
- * 2. $gtm_dist need to point to the current directory from which
- * mumps and mupip were being executed from. This is verified
- * in gtm_chk_dist() to avoid gtmsecshr forking errors later on.
- * see C9808-000615
- * 3. $gtm_dist/gtmsecshr has setuid privs and is owned by root
- * gtm_chk_image()
- * 4. the current image is $gtm_dist/mumps
- * If either of these are not true, it exits.
+ *
+ * 1. $gtm_dist is defined
+ *
+ * 2. Ensure that the executable resides in $gtm_dist. This provides enough
+ * assurance that $gtm_dist is suitable for use.
+ *
+ * This comparison is done using the inode of the executable in $gtm_dist
+ * and the discovered executable path, either from /proc or other OS
+ * function. Using argv[0] wasn't possible when $gtm_dist is in the $PATH.
+ *
+ * The GT.CM servers, OMI and GNP, always defer issuing an error for an
+ * unverified $gtm_dist. All other executables, MUMPS, MUPIP, DSE, and LKE
+ * issue the error messages as soon as possible.
+ *
+ * 3. Checking that $gtm_dist/gtmsecshr was relocated to secshr_client()
************************************************************************************/
#include "mdef.h"
@@ -41,67 +47,120 @@
#include "gtmimagename.h"
#include "have_crit.h"
-GBLREF char gtm_dist[GTM_PATH_MAX];
-LITREF gtmImageName gtmImageNames[];
+/* HPUX does not have a /proc filesystem to retrieve the exe's path. The
+ * following link leads to a forum thread in which the user yrpark shows the
+ * desired result.
+ * http://h30499.www3.hp.com/t5/Languages-and-Scripting/Get-full-path-of-executable-of-running-process/td-p/5135520#.U-o1W3X7GV4
+ */
+#if defined(__hpux)
+#include <sys/pstat.h>
+#endif
+
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
+LITREF gtmImageName gtmImageNames[];
+GBLREF uint4 process_id;
error_def(ERR_DISTPATHMAX);
error_def(ERR_SYSCALL);
error_def(ERR_GTMDISTUNDEF);
+error_def(ERR_GTMDISTUNVERIF);
error_def(ERR_FILEPARSE);
error_def(ERR_MAXGTMPATH);
error_def(ERR_IMAGENAME);
+error_def(ERR_TEXT);
int gtm_chk_dist(char *image)
{
- char pre_buff[MAX_FBUFF];
- char *prefix;
- int prefix_len;
- mstr gtm_name;
- int status;
- char mbuff[MAX_FBUFF + 1];
- parse_blk pblk;
+ char *real_dist;
+ char *imagepath;
+ char *exename;
+ int exename_len;
+ int path_len;
+ int gtm_dist_len;
+ boolean_t status;
+ boolean_t is_gtcm_image;
+ char image_real_path[GTM_PATH_MAX];
+ char real_gtm_dist_path[GTM_PATH_MAX];
+ char comparison[GTM_PATH_MAX];
- if (STRLEN(gtm_dist))
+ is_gtcm_image = (IS_GTCM_GNP_SERVER_IMAGE || IS_GTCM_SERVER_IMAGE); /* GT.CM servers defer issuing errors until startup */
+ /* Use the real path while checking the path length. If not valid, let it fail when checking is_file_identical */
+ real_dist = realpath(gtm_dist, real_gtm_dist_path);
+ if (real_dist)
{
- assert(IS_VALID_IMAGE && (n_image_types > image_type)); /* assert image_type is initialized */
- if ((GTM_PATH_MAX - 2) <= (STRLEN(gtm_dist) + gtmImageNames[image_type].imageNameLen))
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_DISTPATHMAX, 1,
- GTM_PATH_MAX - gtmImageNames[image_type].imageNameLen - 2);
+ STRNLEN(real_dist, GTM_PATH_MAX, gtm_dist_len);
} else
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GTMDISTUNDEF);
- memset(&pblk, 0, SIZEOF(pblk));
- pblk.buffer = mbuff;
- pblk.buff_size = MAX_FBUFF;
- pblk.fop = F_SYNTAXO;
- gtm_name.addr = image;
- gtm_name.len = STRLEN(image);
- /* strings returned in pblk are not null terminated */
- status = parse_file(>m_name, &pblk);
- if (!(status & 1))
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, gtm_name.len, gtm_name.addr, status);
- assert(NULL != pblk.l_name);
- if ((!(pblk.fnb & F_HAS_DIR) && !pblk.b_dir) || (DIR_SEPARATOR != pblk.l_dir[0]))
{
- GETCWD(pre_buff, MAX_FBUFF, prefix);
- if (NULL == prefix)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("getcwd"), CALLFROM, errno);
- prefix_len = STRLEN(prefix);
- if (MAX_FBUFF < prefix_len + pblk.b_esl + 1)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_MAXGTMPATH, 1, MAX_FBUFF - pblk.b_name);
- if (DIR_SEPARATOR != prefix[prefix_len - 1])
+ STRNLEN(gtm_dist, GTM_PATH_MAX, gtm_dist_len);
+ }
+ if (gtm_dist_len)
+ {
+ assert(IS_VALID_IMAGE && (n_image_types > image_type)); /* assert image_type is initialized */
+ if (GTM_DIST_PATH_MAX <= gtm_dist_len)
{
- prefix[prefix_len] = DIR_SEPARATOR;
- prefix[++prefix_len] = 0;
+ if (is_gtcm_image)
+ return 0;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_DISTPATHMAX, 1, GTM_DIST_PATH_MAX);
}
- memcpy(prefix + prefix_len, pblk.l_dir, (int)pblk.b_dir);
- prefix[prefix_len + (int)pblk.b_dir] = 0;
} else
{
- prefix = pblk.l_dir;
- if (DIR_SEPARATOR == prefix[pblk.b_dir])
- prefix[pblk.b_dir] = 0;
+ if (is_gtcm_image)
+ return 0;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GTMDISTUNDEF);
}
- if (IS_GTM_IMAGE && memcmp(pblk.l_name, GTM_IMAGE_NAME, GTM_IMAGE_NAMELEN))
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_IMAGENAME, 4, LEN_AND_LIT(GTM_IMAGE_NAME), pblk.b_name, pblk.l_name);
+
+ /* Get the executable name and length */
+ exename = strrchr(image, '/');
+ if (!exename) /* no slash found, then image is just the exe's name */
+ {
+ exename = image;
+ } else /* slash found in the path, advance the pointer by one to get the name */
+ exename++;
+ STRNLEN(exename, GTM_PATH_MAX, exename_len);
+
+ status = gtm_image_path(image_real_path);
+ if (status) /* On HP-UX it's possible for the underlying system call to return an error. Fall back to realpath() */
+ {
+ /* Use the return of realpath(). If it returns null for argv[0], just use image and let the check fail */
+ imagepath = realpath(image, image_real_path);
+ if (NULL == imagepath)
+ imagepath = image;
+ } else
+ imagepath = image_real_path;
+ /* create the comparison path (gtm_dist + '/' + exename + '\0') and compare it to imagepath */
+ SNPRINTF(comparison, GTM_PATH_MAX, "%s/%s", gtm_dist, exename);
+ status = is_file_identical(imagepath, comparison);
+ if (status)
+ gtm_dist_ok_to_use = TRUE;
+ else
+ {
+ if (is_gtcm_image)
+ return 0;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, LEN_AND_STR(gtm_dist), LEN_AND_STR(image));
+ }
+
+ if (IS_GTM_IMAGE && memcmp(exename, GTM_IMAGE_NAME, GTM_IMAGE_NAMELEN))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_IMAGENAME, 4, LEN_AND_LIT(GTM_IMAGE_NAME), LEN_AND_STR(exename));
+ return 0;
+}
+
+int gtm_image_path(char *realpath)
+{
+#if defined(__hpux)
+ int status = 0;
+ struct pst_status pst;
+ pst.pst_pid = -1;
+ /* The man page for pstat_getproc does not list in/valid return codes, so we ignore it */
+ pstat_getproc(&pst, SIZEOF(struct pst_status), 0, process_id);
+ status = pstat_getpathname(realpath, GTM_PATH_MAX, &pst.pst_fid_text);
+ assertpro(status != 0); /* Can only happen if the path name is not in the system cache */
+ if (status < 0) /* errno is set */
+ return status;
+#elif defined(__linux__) || defined(__sparc) || defined(_AIX)
+ SNPRINTF(realpath, GTM_PATH_MAX, PROCSELF, process_id);
+#else
+# error "Unsupported platform : no way to determine the true exe path"
+#endif
return 0;
}
diff --git a/sr_unix/gtm_startup_chk.h b/sr_unix/gtm_startup_chk.h
index 5bd5e7c..407335c 100644
--- a/sr_unix/gtm_startup_chk.h
+++ b/sr_unix/gtm_startup_chk.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,7 +12,14 @@
#ifndef __GTM_STARTUP_CHK_H__
#define __GTM_STARTUP_CHK_H__
-int gtm_chk_dist(char *image);
-int gtm_chk_image(void);
+#if defined(__linux__)
+#define PROCSELF "/proc/self/exe"
+#elif defined(__sparc)
+#define PROCSELF "/proc/%d/path/a.out"
+#elif defined(_AIX)
+#define PROCSELF "/proc/%d/object/a.out"
+#endif
+int gtm_chk_dist(char *image);
+int gtm_image_path(char *realpath);
#endif
diff --git a/sr_unix/gtm_system.c b/sr_unix/gtm_system.c
index 76f2850..fcb23c8 100644
--- a/sr_unix/gtm_system.c
+++ b/sr_unix/gtm_system.c
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2013 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#include "mdef.h"
#include <sys/wait.h>
#include <errno.h>
diff --git a/sr_unix/gtm_test_install.csh b/sr_unix/gtm_test_install.csh
index 69bec11..532116e 100644
--- a/sr_unix/gtm_test_install.csh
+++ b/sr_unix/gtm_test_install.csh
@@ -1,7 +1,7 @@
#!/usr/local/bin/tcsh
#################################################################
# #
-# Copyright 2011, 2013 Fidelity Information Services, Inc #
+# Copyright 2011, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -220,11 +220,17 @@ EOF
setenv gtmdir $save_gtm_dist/test_gtm_utf8
# make gtm set the utf locale
unsetenv LC_CTYPE
+ # unset gtm_icu_version to test gtmprofile.gtc setting it using icu-config
+ setenv save_icu $gtm_icu_version
+ unsetenv gtm_icu_version
+ # NOTE: this is not the alias gtm, but the script sr_unix/gtm.gtc
../gtm -r sim >& gtm.out
# get $ZCHSET
echo "" >>&! $save_gtm_dist/gtm_test_install.out
grep ZCHSET gtm.out >>&! $save_gtm_dist/gtm_test_install.out
+ # restore saved gtm_icu_version
+ setenv gtm_icu_version $save_icu
# test gtmsecshr with an alternate user
set XCMD='do ^GTMHELP("",$ztrnlnm("gtm_dist")_"/gtmhelp.gld")'
su - gtmtest -c "env LD_LIBRARY_PATH=$libpath LC_ALL=$LC_ALL gtm_chset=UTF-8 gtm_dist=$gtm_dist gtmroutines='$gtmroutines' $gtm_dist/mumps -run %XCMD '${XCMD:q}' < /dev/null" > gtmtest.out #BYPASSOK line length
diff --git a/sr_unix/gtm_tls_impl.c b/sr_unix/gtm_tls_impl.c
index be33fbf..920e345 100644
--- a/sr_unix/gtm_tls_impl.c
+++ b/sr_unix/gtm_tls_impl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -233,17 +233,17 @@ STATICFNDEF DH *tmp_dh_callback(SSL *ssl, int is_export, int keylength)
return (512 == keylength) ? dh512 : dh1024;
}
-_GTM_APIDEF int gtm_tls_errno(void)
+int gtm_tls_errno(void)
{
return tls_errno;
}
-_GTM_APIDEF const char *gtm_tls_get_error(void)
+const char *gtm_tls_get_error(void)
{
return gtmcrypt_err_string;
}
-_GTM_APIDEF gtm_tls_ctx_t *gtm_tls_init(int version, int flags)
+gtm_tls_ctx_t *gtm_tls_init(int version, int flags)
{
const char *CAfile = NULL, *CApath = NULL, *crl, *CAptr;
char *config_env;
@@ -391,7 +391,7 @@ _GTM_APIDEF gtm_tls_ctx_t *gtm_tls_init(int version, int flags)
return gtm_tls_ctx;
}
-_GTM_APIDEF void gtm_tls_prefetch_passwd(gtm_tls_ctx_t *tls_ctx, char *env_name)
+void gtm_tls_prefetch_passwd(gtm_tls_ctx_t *tls_ctx, char *env_name)
{
char *env_name_ptr, *env_value, prompt[256];
gtmtls_passwd_list_t *pwent_node;
@@ -418,7 +418,7 @@ _GTM_APIDEF void gtm_tls_prefetch_passwd(gtm_tls_ctx_t *tls_ctx, char *env_name)
*/
}
-_GTM_APIDEF gtm_tls_socket_t *gtm_tls_socket(gtm_tls_ctx_t *tls_ctx, gtm_tls_socket_t *prev_socket, int sockfd, char *id, int flags)
+gtm_tls_socket_t *gtm_tls_socket(gtm_tls_ctx_t *tls_ctx, gtm_tls_socket_t *prev_socket, int sockfd, char *id, int flags)
{
int len;
char cfg_path[MAX_CONFIG_LOOKUP_PATHLEN], input_env_name[PASSPHRASE_ENVNAME_MAX], *env_name_ptr;
@@ -613,7 +613,7 @@ _GTM_APIDEF gtm_tls_socket_t *gtm_tls_socket(gtm_tls_ctx_t *tls_ctx, gtm_tls_soc
return socket;
}
-_GTM_APIDEF int gtm_tls_connect(gtm_tls_socket_t *socket)
+int gtm_tls_connect(gtm_tls_socket_t *socket)
{
int rv;
@@ -635,7 +635,7 @@ _GTM_APIDEF int gtm_tls_connect(gtm_tls_socket_t *socket)
return ssl_error(socket->ssl, rv);
}
-_GTM_APIDEF int gtm_tls_accept(gtm_tls_socket_t *socket)
+int gtm_tls_accept(gtm_tls_socket_t *socket)
{
int rv;
@@ -645,7 +645,7 @@ _GTM_APIDEF int gtm_tls_accept(gtm_tls_socket_t *socket)
return ssl_error(socket->ssl, rv);
}
-_GTM_APIDEF int gtm_tls_renegotiate(gtm_tls_socket_t *socket)
+int gtm_tls_renegotiate(gtm_tls_socket_t *socket)
{
int rv;
@@ -667,7 +667,7 @@ _GTM_APIDEF int gtm_tls_renegotiate(gtm_tls_socket_t *socket)
return rv;
}
-_GTM_APIDEF int gtm_tls_get_conn_info(gtm_tls_socket_t *socket, gtm_tls_conn_info *conn_info)
+int gtm_tls_get_conn_info(gtm_tls_socket_t *socket, gtm_tls_conn_info *conn_info)
{
long verify_result, timeout, creation_time;
unsigned int session_id_length, ssl_version;
@@ -778,7 +778,7 @@ _GTM_APIDEF int gtm_tls_get_conn_info(gtm_tls_socket_t *socket, gtm_tls_conn_in
return -1;
}
-_GTM_APIDEF int gtm_tls_send(gtm_tls_socket_t *socket, char *buf, int send_len)
+int gtm_tls_send(gtm_tls_socket_t *socket, char *buf, int send_len)
{
int rv;
@@ -791,7 +791,7 @@ _GTM_APIDEF int gtm_tls_send(gtm_tls_socket_t *socket, char *buf, int send_len)
return ssl_error(socket->ssl, rv);
}
-_GTM_APIDEF int gtm_tls_recv(gtm_tls_socket_t * socket, char *buf, int recv_len)
+int gtm_tls_recv(gtm_tls_socket_t * socket, char *buf, int recv_len)
{
int rv;
@@ -804,12 +804,12 @@ _GTM_APIDEF int gtm_tls_recv(gtm_tls_socket_t * socket, char *buf, int recv_len
return ssl_error(socket->ssl, rv);
}
-_GTM_APIDEF int gtm_tls_cachedbytes(gtm_tls_socket_t *socket)
+int gtm_tls_cachedbytes(gtm_tls_socket_t *socket)
{
return SSL_pending(socket->ssl);
}
-_GTM_APIDEF void gtm_tls_socket_close(gtm_tls_socket_t *socket)
+void gtm_tls_socket_close(gtm_tls_socket_t *socket)
{
assert(socket);
tls_errno = 0;
@@ -827,7 +827,7 @@ _GTM_APIDEF void gtm_tls_socket_close(gtm_tls_socket_t *socket)
socket->ssl = NULL;
}
-_GTM_APIDEF void gtm_tls_session_close(gtm_tls_socket_t **socket)
+void gtm_tls_session_close(gtm_tls_socket_t **socket)
{
SSL_SESSION *session;
gtm_tls_socket_t *sock;
@@ -846,7 +846,7 @@ _GTM_APIDEF void gtm_tls_session_close(gtm_tls_socket_t **socket)
*socket = NULL;
}
-_GTM_APIDEF void gtm_tls_fini(gtm_tls_ctx_t **tls_ctx)
+void gtm_tls_fini(gtm_tls_ctx_t **tls_ctx)
{
gtmtls_passwd_list_t *node, *prev_node;
diff --git a/sr_unix/gtm_tls_impl.h b/sr_unix/gtm_tls_impl.h
index 1340186..82abc2d 100644
--- a/sr_unix/gtm_tls_impl.h
+++ b/sr_unix/gtm_tls_impl.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -48,7 +48,7 @@ typedef struct gtmtls_passwd_list_struct
#define DBG_VERIFY_AUTORETRY_SET(TLS_DESC) assert(SSL_MODE_AUTO_RETRY & SSL_CTX_get_mode((SSL_CTX *)TLS_DESC));
#else
-#define DBG_VERIFY_SOCK_IS_NONBLOCKING(SOCKFD)
+#define DBG_VERIFY_SOCK_IS_BLOCKING(SOCKFD)
#define DBG_VERIFY_AUTORETRY_SET(TLS_DESC)
#endif
diff --git a/sr_unix/gtm_tls_interface.h b/sr_unix/gtm_tls_interface.h
index 94309b8..e984308 100644
--- a/sr_unix/gtm_tls_interface.h
+++ b/sr_unix/gtm_tls_interface.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -92,12 +92,12 @@ typedef struct gtm_tls_ctx_struct
*/
/* Returns the most recent error (null-terminated) related to the workings of the SSL/TLS reference implementation. */
-_GTM_APIDECL const char *gtm_tls_get_error(void);
+const char *gtm_tls_get_error(void);
/* If the most recent invocation of the SSL/TLS reference implementation resulted in a system call error, `gtm_tls_errno' returns
* the value of `errno'. Otherwise, -1 is returned in which case `gtm_tls_get_error' provides more information.
*/
-_GTM_APIDECL int gtm_tls_errno(void);
+int gtm_tls_errno(void);
/* Initializes the SSL/TLS context for a process. Typically invoked only once (unless the previous attempt failed). Attributes
* necessary to initialize the SSL/TLS context are obtained from the configuration file pointed to by `$gtmcrypt_config'.
@@ -112,7 +112,7 @@ _GTM_APIDECL int gtm_tls_errno(void);
* application, to create as many SSL/TLS aware sockets as needed. In case of an error, INVALID_TLS_CONTEXT is returned in which
* case gtm_tls_get_error() provides the necessary error detail.
*/
-_GTM_APIDECL gtm_tls_ctx_t *gtm_tls_init(int version, int flags);
+gtm_tls_ctx_t *gtm_tls_init(int version, int flags);
/* Prefetches the password corresponding to a private key.
*
@@ -134,7 +134,7 @@ _GTM_APIDECL gtm_tls_ctx_t *gtm_tls_init(int version, int flags);
* Note 2: The function honors the GTMTLS_OP_INTERACTIVE_MODE flag passed to the `gtm_tls_init' function. If the application has
* initialized the SSL/TLS API in a non-interactive mode, the API does not prompt the user for password.
*/
-_GTM_APIDECL void gtm_tls_prefetch_passwd(gtm_tls_ctx_t *tls_ctx, char *env_name);
+void gtm_tls_prefetch_passwd(gtm_tls_ctx_t *tls_ctx, char *env_name);
/* Converts a Unix TCP/IP socket into a SSL/TLS aware socket.
*
@@ -159,7 +159,7 @@ _GTM_APIDECL void gtm_tls_prefetch_passwd(gtm_tls_ctx_t *tls_ctx, char *env_nam
* Note 2: The function honors the GTMTLS_OP_INTERACTIVE_MODE flag passed to the `gtm_tls_init' function. If the application has
* initialized the SSL/TLS API in a non-interactive mode, this function does not prompt the user for password.
*/
-_GTM_APIDECL gtm_tls_socket_t *gtm_tls_socket(gtm_tls_ctx_t *ctx, gtm_tls_socket_t *prev_socket, int sockfd, char *id, int flags);
+gtm_tls_socket_t *gtm_tls_socket(gtm_tls_ctx_t *ctx, gtm_tls_socket_t *prev_socket, int sockfd, char *id, int flags);
/* Connects using SSL/TLS aware socket. Assumes the other transport endpoint understands SSL/TLS.
*
@@ -171,7 +171,7 @@ _GTM_APIDECL gtm_tls_socket_t *gtm_tls_socket(gtm_tls_ctx_t *ctx, gtm_tls_socket
*
* Note: The function makes use of an existing SSL session (if one is available).
*/
-_GTM_APIDECL int gtm_tls_connect(gtm_tls_socket_t *socket);
+int gtm_tls_connect(gtm_tls_socket_t *socket);
/* Accepts an incoming connection using SSL/TLS aware socket. Assumes the other transport endpoint understands SSL/TLS.
*
@@ -182,7 +182,7 @@ _GTM_APIDECL int gtm_tls_connect(gtm_tls_socket_t *socket);
* -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain the necessary error detail.
*
*/
-_GTM_APIDECL int gtm_tls_accept(gtm_tls_socket_t *socket);
+int gtm_tls_accept(gtm_tls_socket_t *socket);
/* Renegotiates an active SSL/TLS connection. Note: This function does the renegotiation in a blocking fashion and more importantly
* handles EINTR internally by retrying the renegotiation.
@@ -192,7 +192,7 @@ _GTM_APIDECL int gtm_tls_accept(gtm_tls_socket_t *socket);
*
* Return value: none.
*/
-_GTM_APIDECL int gtm_tls_renegotiate(gtm_tls_socket_t *socket);
+int gtm_tls_renegotiate(gtm_tls_socket_t *socket);
/* Obtains additional SSL/TLS related information on the peer. This function is typically invoked to log information for diagnostic
* purposes.
@@ -205,7 +205,7 @@ _GTM_APIDECL int gtm_tls_renegotiate(gtm_tls_socket_t *socket);
* GTMTLS_WANT_WRITE is returned. In case of -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain the necessary error
* detail.
*/
-_GTM_APIDECL int gtm_tls_get_conn_info(gtm_tls_socket_t *socket, gtm_tls_conn_info *conn_info);
+int gtm_tls_get_conn_info(gtm_tls_socket_t *socket, gtm_tls_conn_info *conn_info);
/* Transmits message securely to the transport endpoint. This function should be invoked ONLY after successful invocations of either
* `gtm_tls_connect' or `gtm_tls_accept'.
@@ -219,7 +219,7 @@ _GTM_APIDECL int gtm_tls_get_conn_info(gtm_tls_socket_t *socket, gtm_tls_conn_i
* GTMTLS_WANT_READ or GTMTLS_WANT_WRITE is returned. In case of -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain
* the necessary error detail.
*/
-_GTM_APIDECL int gtm_tls_send(gtm_tls_socket_t *socket, char *buf, int send_len);
+int gtm_tls_send(gtm_tls_socket_t *socket, char *buf, int send_len);
/* Receives message securely from the transport endpoint. This function should be invoked ONLY after successful invocations of
* either `gtm_tls_connect' or `gtm_tls_accept'.
@@ -234,7 +234,7 @@ _GTM_APIDECL int gtm_tls_send(gtm_tls_socket_t *socket, char *buf, int send_len
* GTMTLS_WANT_READ or GTMTLS_WANT_WRITE is returned. In case of -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain
* the necessary error detail.
*/
-_GTM_APIDECL int gtm_tls_recv(gtm_tls_socket_t *socket, char *buf, int recv_len);
+int gtm_tls_recv(gtm_tls_socket_t *socket, char *buf, int recv_len);
/* Returns the number of bytes cached in the SSL/TLS layer and is ready for immediate retrieval with the `gtm_tls_recv'.
*
@@ -246,7 +246,7 @@ _GTM_APIDECL int gtm_tls_recv(gtm_tls_socket_t *socket, char *buf, int recv_len
* or `poll' on the underlying TCP/IP socket indicates that the subsequent `recv' will block, and check if there are any bytes
* readily available.
*/
-_GTM_APIDECL int gtm_tls_cachedbytes(gtm_tls_socket_t *socket);
+int gtm_tls_cachedbytes(gtm_tls_socket_t *socket);
/* Close the SSL/TLS socket connection.
*
@@ -260,7 +260,7 @@ _GTM_APIDECL int gtm_tls_cachedbytes(gtm_tls_socket_t *socket);
* necessary error detail.
*
*/
-_GTM_APIDECL void gtm_tls_socket_close(gtm_tls_socket_t *socket);
+void gtm_tls_socket_close(gtm_tls_socket_t *socket);
/* Closes an active SSL/TLS session. This frees up the session and thus makes the session not resuable for a future connection.
* Any subsequent connection will create a new session.
@@ -268,7 +268,7 @@ _GTM_APIDECL void gtm_tls_socket_close(gtm_tls_socket_t *socket);
* Note: The function takes a pointer to the gtm_tls_socket_t structure. This is because it forces the actual `socket' value to be
* INVALID_TLS_SOCKET.
*/
-_GTM_APIDECL void gtm_tls_session_close(gtm_tls_socket_t **socket);
+void gtm_tls_session_close(gtm_tls_socket_t **socket);
/* Frees up any memory allocated by the SSL/TLS context. This function should typically be invoked at process exit.
*
@@ -280,6 +280,6 @@ _GTM_APIDECL void gtm_tls_session_close(gtm_tls_socket_t **socket);
* Note: The function takes a pointer to the gtm_tls_ctx_t structure. This is because it forces the actual `ctx' value to be
* INVALID_TLS_CONTEXT.
*/
-_GTM_APIDECL void gtm_tls_fini(gtm_tls_ctx_t **ctx);
+void gtm_tls_fini(gtm_tls_ctx_t **ctx);
#endif
diff --git a/sr_unix/gtm_tls_loadlibrary.c b/sr_unix/gtm_tls_loadlibrary.c
index 6ff631d..7803941 100644
--- a/sr_unix/gtm_tls_loadlibrary.c
+++ b/sr_unix/gtm_tls_loadlibrary.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,10 +42,11 @@ gtm_tls_func_n /* total number of TLS functions that needs to be dlsym()ed */
#define GTM_TLS_LIBNAME "libgtmtls.so"
-GBLREF char dl_err[MAX_ERRSTR_LEN];
-GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF char dl_err[MAX_ERRSTR_LEN];
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
-error_def(ERR_GTMDISTUNDEF);
+error_def(ERR_GTMDISTUNVERIF);
/* Cannot include gtm_tls.h in this module due to conflicting GBLDEF/GBLREFs. So, redefine the function prototype here to silent
* the compiler.
@@ -77,7 +78,12 @@ int gtm_tls_loadlibrary()
char save_libpath[GTM_PATH_MAX];
# endif
- assert(STRLEN(gtm_dist));
+ if(!gtm_dist_ok_to_use)
+ {
+ SNPRINTF(dl_err, MAX_ERRSTR_LEN, "%%GTM-E-GTMDISTUNVERIF, Environment variable $gtm_dist (%s) "
+ "could not be verified against the executables path", gtm_dist);
+ return -1;
+ }
# ifdef _AIX
SNPRINTF(plugin_dir_path, GTM_PATH_MAX, "%s/%s", gtm_dist, GTMCRYPT_PLUGIN_DIR_NAME);
SNPRINTF(libpath, GTM_PATH_MAX, "%s/%s/%s", gtm_dist, GTMCRYPT_PLUGIN_DIR_NAME, GTM_TLS_LIBNAME);
diff --git a/sr_unix/gtm_trigger.c b/sr_unix/gtm_trigger.c
index bfdddf4..dd96b71 100644
--- a/sr_unix/gtm_trigger.c
+++ b/sr_unix/gtm_trigger.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -62,6 +62,7 @@
#include "srcline.h"
#include "zshow.h"
#include "zwrite.h"
+#include "zr_unlink_rtn.h"
#ifdef GTM_TRIGGER
#define PREFIX_SPACE " "
@@ -189,44 +190,44 @@ void gtm_levl_ret_code(void);
STATICFNDEF int gtm_trigger_invoke(void);
/* gtm_trigger - saves (some of) current environment, sets up new environment and drives a trigger.
-
- Triggers are one of two places where compiled M code is driven while the C stack is not at a constant level.
- The other place that does this is call-ins. Because this M code invocation needs to be separate from other
- running code, a new running environment is setup with its own base frame to prevent random unwinding back
- into earlier levels. All returns from the invoked generated code come back through gtm_trigger_invoke() with
- the exception of error handling looking for a handler or not having an error "handled" (clearing $ECODE) can
- just keep unwinding until all trigger levels are gone.
-
- Trigger names:
-
- Triggers have a base name set by MUPIP TRIGGER in the TRIGNAME hasht entry which is read by gv_trigger.c and
- passed to us. If it collides with an existing trigger name, we add some suffixing to it (up to two chars)
- and create it with that name.
-
- Trigger compilation:
-
- - When a trigger is presented to us for the first time, it needs to be compiled. We do this by writing it out
- using a system generated unique name to a temp file and compiling it with the -NAMEOFRTN parameter which
- sets the name of the routine different than the unique random object name.
- - The file is then linked in and its address recorded so the compilation only happens once.
-
- Trigger M stack format:
-
- - First created frame is a "base frame" (created by base_frame). This frame is set up to return to us
- (the caller) and has no backchain (old_frame_pointer is null). It also has the type SFT_TRIGR | SFT_COUNT
- so it is a counted frame (it is important to be counted so the mv_stents we create don't try to backup to
- a previous counted frame.
- - The second created frame is for the trigger being executed. We fill in the stack_frame from the trigger
- description and then let it rip by calling dm_start(). When the trigger returns through the base frame
- which calls gtm_levl_ret_code and pulls the return address of our call to dm_start off the stack and
- unwinds the appropriate saved regs, it returns back to us.
-
- Error handling in a trigger frame:
-
- - $ETRAP only. $ZTRAP is forbidden. Standard rules apply.
- - Error handling does not return to the trigger base frame but unwinds the base frame doing a rollback if
- necessary.
-*/
+ *
+ * Triggers are one of two places where compiled M code is driven while the C stack is not at a constant level.
+ * The other place that does this is call-ins. Because this M code invocation needs to be separate from other
+ * running code, a new running environment is setup with its own base frame to prevent random unwinding back
+ * into earlier levels. All returns from the invoked generated code come back through gtm_trigger_invoke() with
+ * the exception of error handling looking for a handler or not having an error "handled" (clearing $ECODE) can
+ * just keep unwinding until all trigger levels are gone.
+ *
+ * Trigger names:
+ *
+ * Triggers have a base name set by MUPIP TRIGGER in the TRIGNAME hasht entry which is read by gv_trigger.c and
+ * passed to us. If it collides with an existing trigger name, we add some suffixing to it (up to two chars)
+ * and create it with that name.
+ *
+ * Trigger compilation:
+ *
+ * - When a trigger is presented to us for the first time, it needs to be compiled. We do this by writing it out
+ * using a system generated unique name to a temp file and compiling it with the -NAMEOFRTN parameter which
+ * sets the name of the routine different than the unique random object name.
+ * - The file is then linked in and its address recorded so the compilation only happens once.
+ *
+ * Trigger M stack format:
+ *
+ * - First created frame is a "base frame" (created by base_frame). This frame is set up to return to us
+ * (the caller) and has no backchain (old_frame_pointer is null). It also has the type SFT_TRIGR | SFT_COUNT
+ * so it is a counted frame (it is important to be counted so the mv_stents we create don't try to backup to
+ * a previous counted frame.
+ * - The second created frame is for the trigger being executed. We fill in the stack_frame from the trigger
+ * description and then let it rip by calling dm_start(). When the trigger returns through the base frame
+ * which calls gtm_levl_ret_code and pulls the return address of our call to dm_start off the stack and
+ * unwinds the appropriate saved regs, it returns back to us.
+ *
+ * Error handling in a trigger frame:
+ *
+ * - $ETRAP only. $ZTRAP is forbidden. Standard rules apply.
+ * - Error handling does not return to the trigger base frame but unwinds the base frame doing a rollback if
+ * necessary.
+ */
CONDITION_HANDLER(gtm_trigger_complink_ch)
{ /* Condition handler for trigger compilation and link - be noisy but don't error out. Note that compilations do
@@ -259,10 +260,10 @@ CONDITION_HANDLER(gtm_trigger_complink_ch)
CONDITION_HANDLER(gtm_trigger_ch)
{ /* Condition handler for trigger execution - This handler is pushed on first for a given trigger level, then
- mdb_condition_handler is pushed on so will appearr multiple times as trigger depth increases. There is
- always an mdb_condition_handler behind us for an earlier trigger level and we let it handle severe
- errors for us as it gives better diagnostics (e.g. GTM_FATAL_ERROR dumps) in addition to the file core dump.
- */
+ * mdb_condition_handler is pushed on so will appearr multiple times as trigger depth increases. There is
+ * always an mdb_condition_handler behind us for an earlier trigger level and we let it handle severe
+ * errors for us as it gives better diagnostics (e.g. GTM_FATAL_ERROR dumps) in addition to the file core dump.
+ */
START_CH(TRUE);
DBGTRIGR((stderr, "gtm_trigger_ch: Failsafe condition cond handler entered with SIGNAL = %d\n", SIGNAL));
if (DUMPABLE)
@@ -510,7 +511,7 @@ int gtm_trigger(gv_trigger_t *trigdsc, gtm_trigger_parms *trigprm)
mv_stent *mv_st_ent;
symval *new_symval;
uint4 dollar_tlevel_start;
- stack_frame *fp, *fpprev;
+ stack_frame *fp;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -864,15 +865,11 @@ void gtm_trigger_fini(boolean_t forced_unwind, boolean_t fromzgoto)
*/
void gtm_trigger_cleanup(gv_trigger_t *trigdsc)
{
- rtn_tabent *rbot, *mid, *rtop;
+ rtn_tabent *mid;
mident *rtnname;
rhdtyp *rtnhdr;
- textElem *telem;
- int comp, size;
- stack_frame *fp, *fpprev;
- mname_entry key;
- ht_ent_mname *tabent;
- routine_source *src_tbl;
+ int size;
+ stack_frame *fp;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -886,96 +883,29 @@ void gtm_trigger_cleanup(gv_trigger_t *trigdsc)
/* Next thing to do is find the routine header in the rtn_names list so we can remove it. */
rtnname = &trigdsc->rtn_desc.rt_name;
rtnhdr = trigdsc->rtn_desc.rt_adr;
- rbot = rtn_names;
- rtop = rtn_names_end;
- for (;;)
- { /* See if routine exists in list via a binary search which reverts to serial
- search when # of items drops below the threshold S_CUTOFF.
- */
- if ((rtop - rbot) < S_CUTOFF)
- {
- comp = -1;
- for (mid = rbot; mid <= rtop ; mid++)
- {
- MIDENT_CMP(&mid->rt_name, rtnname, comp);
- if (0 == comp)
- break;
- assertpro(0 >= comp); /* Routine should be found */
- }
- break;
- } else
- { mid = rbot + (rtop - rbot)/2;
- MIDENT_CMP(&mid->rt_name, rtnname, comp);
- if (0 == comp)
- break;
- else if (0 > comp)
- {
- rbot = mid + 1;
- continue;
- } else
- {
- rtop = mid - 1;
- continue;
- }
- }
- }
-# ifdef DEBUG
- assert(rtnhdr == mid->rt_adr);
+ /* Only one possible version of a trigger routine */
+ assert(USHBIN_ONLY(NULL) NON_USHBIN_ONLY(rtnhdr) == OLD_RHEAD_ADR(CURRENT_RHEAD_ADR(rtnhdr)));
/* Verify trigger routine we want to remove is not currently active. If it is, we need to assert fail.
* Triggers are not like regular routines since they should only ever be referenced from the stack during a
* transaction. Likewise, we should only ever load the triggers as the first action in that transaction.
*/
- for (fp = frame_pointer; fp ; fp = fpprev)
- {
- fpprev = fp->old_frame_pointer;
-# ifdef GTM_TRIGGER
- if (NULL != fpprev && SFT_TRIGR & fpprev->type)
- fpprev = *(stack_frame **)(fpprev + 1);
-# endif
- /* Only one possible version of a trigger routine */
- assert(USHBIN_ONLY(NULL) NON_USHBIN_ONLY(fp->rvector) == OLD_RHEAD_ADR(CURRENT_RHEAD_ADR(fp->rvector)));
+# ifdef DEBUG
+ for (fp = frame_pointer; NULL != fp; fp = SKIP_BASE_FRAME(fp->old_frame_pointer))
assert(fp->rvector != rtnhdr);
- }
# endif
- /* Remove break points in this routine before rmv from rtntbl */
- zr_remove(rtnhdr, BREAKMSG);
- /* Release any $TEXT() info this trigger has loaded */
- free_src_tbl(rtnhdr);
+ /* Locate the routine in the routine table while all the pieces are available. Then remove from routine table
+ * after the routine is unlinked.
+ */
+ assertpro(find_rtn_tabent(&mid, rtnname)); /* Routine should be found (sets "mid" with found entry) */
+ assert(rtnhdr == mid->rt_adr);
+ /* Free all storage allocated on behalf of this trigger routine. Do this before removing from routine table since
+ * some of the activities called during unlink look for the routine so it must be found.
+ */
+ zr_unlink_rtn(rtnhdr, TRUE);
/* Remove the routine from the rtn_table */
size = INTCAST((char *)rtn_names_end - (char *)mid);
if (0 < size)
memmove((char *)mid, (char *)(mid + 1), size); /* Remove this routine name from sorted table */
rtn_names_end--;
- urx_remove(rtnhdr); /* Remove any unresolved entries */
-# ifdef USHBIN_SUPPORTED
- stp_move((char *)rtnhdr->literal_text_adr,
- (char *)(rtnhdr->literal_text_adr + rtnhdr->literal_text_len));
- GTM_TEXT_FREE(rtnhdr->ptext_adr); /* R/O releasable section */
- free(RW_REL_START_ADR(rtnhdr)); /* R/W releasable section part 1 */
- free(rtnhdr->linkage_adr); /* R/W releasable section part 2 */
- free(rtnhdr->labtab_adr); /* Usually non-releasable but triggers don't have labels so
- * this is just cleaning up a dangling null malloc
- */
- free(rtnhdr);
-# else
-# if (!defined(__linux__) && !defined(__CYGWIN__)) || !defined(__i386) || !defined(COMP_GTA)
-# error Unsupported NON-USHBIN platform
-# endif
- /* For a non-shared binary platform we need to get an approximate addr range for stp_move. This is not
- * done when a routine is replaced on these platforms but in this case we are able to due to the isolated
- * environment if we only take the precautions of migrating potential literal text which may have been
- * pointed to by any set environment variables.
- * In this format, the only platform we support currently is Linux-x86 (i386) which uses GTM_TEXT_ALLOC
- * to allocate special storage for it to put executable code in. We can access the storage header for
- * this storage and find out how big it is and use that information to give stp_move a good range since
- * the literal segment occurs right at the end of allocated storage (for which there is no pointer
- * in the fileheader).
- */
- telem = (textElem *)((char *)rtnhdr - offsetof(textElem, userStorage));
- assert(TextAllocated == telem->state);
- stp_move((char *)LNRTAB_ADR(rtnhdr) + (rtnhdr->lnrtab_len * SIZEOF(lnr_tabent)),
- (char *)rtnhdr + telem->realLen);
- GTM_TEXT_FREE(rtnhdr);
-# endif
}
#endif /* GTM_TRIGGER */
diff --git a/sr_unix/gtm_unique_file_util.c b/sr_unix/gtm_unique_file_util.c
index 858f857..bfe433a 100644
--- a/sr_unix/gtm_unique_file_util.c
+++ b/sr_unix/gtm_unique_file_util.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,6 +13,7 @@
#include "gtmxc_types.h"
#include "gdsroot.h"
#include "is_file_identical.h"
+#include "iosp.h" /* for SS_NORMAL */
/* Checks whether the two fileids passed are identical */
xc_status_t gtm_is_file_identical(xc_fileid_ptr_t fileid1, xc_fileid_ptr_t fileid2)
@@ -26,14 +27,14 @@ xc_status_t gtm_is_file_identical(xc_fileid_ptr_t fileid1, xc_fileid_ptr_t filei
* allocated pointer via gtm_xcfileid_free. */
xc_status_t gtm_filename_to_id(xc_string_t *filename, xc_fileid_ptr_t *fileid)
{
- gd_id_ptr_t tmp_fileid;
boolean_t status;
+ gd_id_ptr_t tmp_fileid;
if (!filename)
return FALSE;
assert(fileid && !*fileid);
tmp_fileid = (gd_id_ptr_t)malloc(SIZEOF(gd_id));
- status = filename_to_id(tmp_fileid, filename->address);
+ status = (SS_NORMAL == filename_to_id(tmp_fileid, filename->address));
*fileid = (xc_fileid_ptr_t)tmp_fileid;
return status;
}
diff --git a/sr_unix/gtm_unlink_all.c b/sr_unix/gtm_unlink_all.c
index 3b5a733..2deb71b 100644
--- a/sr_unix/gtm_unlink_all.c
+++ b/sr_unix/gtm_unlink_all.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2011, 2013 Fidelity Information Services, Inc *
+ * Copyright 2011, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -39,6 +39,7 @@
#include "dm_setup.h" /* for GTM_DMOD */
#include "urx.h"
#include "stringpool.h"
+#include "zr_unlink_rtn.h"
#ifdef GTM_TRIGGER
#include "gv_trigger.h"
#include "gtm_trigger.h"
@@ -106,7 +107,7 @@ void gtm_unlink_all(void)
for (gvt = gv_target_list; gvt; gvt = gvt->next_gvnh)
gvtr_free(gvt);
# endif
- /* Step 5: Unlink all routines, remove $TEXT cache and remove breakpoints.Note that for the purposes of this section,
+ /* Step 5: Unlink all routines, remove $TEXT cache and remove breakpoints. Note that for the purposes of this section,
* there is no difference between normal routines and trigger routines. Both are being removed completely so the code
* below is a hodgepodge of code from zlput_rname and gtm_trigger_cleanup(). Note process in reverse order so we can
* move rtn_names_end up leaving processed entries (whose keys no longer work) off the end of the table without moving
@@ -116,73 +117,13 @@ void gtm_unlink_all(void)
for (rtab = rtn_names_end; rtab > rtn_names; rtab--, rtn_names_end = rtab)
{ /* [0] is not used (for some reason) */
rtnhdr = rtab->rt_adr;
- zr_remove(rtnhdr, FALSE); /* Remove all breakpoints in this routine */
- urx_remove(rtnhdr); /* Remove all unresolved entries for this routine */
- /* If source has been read in for this routine, free the space. Since routine name is the key, do this before
- * (in USHBIN builds) we release the literal text section as part of the releasable read-only section.
- * Note this code is similar to code in zlput_rname() 'cept this is necessarily UNIX-only.
- */
- free_src_tbl(rtnhdr);
if ((0 == strcmp(rtnhdr->routine_name.addr, GTM_DMOD)) || (0 == strcmp(rtnhdr->routine_name.addr, GTM_CIMOD)))
{ /* If the routine is GTM$DMOD or GTM$CIMOD, it is allocated in one chunk by make_*mode(). Release it in
* one chunk too.
*/
GTM_TEXT_FREE(rtnhdr);
} else
- {
-# ifdef USHBIN_SUPPORTED
- /* We are about to release program areas containing literal text that could be pointed to by
- * local var mvals that are being kept so migrate program literals to the stringpool. Note zlput_rname()
- * only does this if not a shared library but since we are releasing shared libraries too, do it
- * regardless.
- */
- if (0 < rtnhdr->literal_text_len)
- {
- stp_move((char *)rtnhdr->literal_text_adr,
- (char *)(rtnhdr->literal_text_adr + rtnhdr->literal_text_len));
- }
- if (NULL == rtnhdr->shlib_handle)
- /* We can only release this section if this is not a shared library */
- GTM_TEXT_FREE(rtnhdr->ptext_adr); /* R/O releasable section */
- free(RW_REL_START_ADR(rtnhdr)); /* R/W releasable section part 1 */
- free(rtnhdr->linkage_adr); /* R/W releasable section part 2 */
- free(rtnhdr->labtab_adr); /* Usually non-releasable but not in this case */
- /* Run the chain of old (replaced) versions freeing them also */
- for (rhdr = OLD_RHEAD_ADR(rtnhdr); NULL != rhdr; rhdr = next_rhdr)
- {
- next_rhdr = rhdr->old_rhead_adr;
- free(rhdr->labtab_adr); /* Free dangling label table */
- free(rhdr);
- }
- free(rtnhdr);
-# else
-# if (!defined(__linux__) && !defined(__CYGWIN__)) || !defined(__i386) || !defined(COMP_GTA)
-# error Unsupported NON-USHBIN platform
-# endif
- /* For a non-shared binary platform we need to get an approximate addr range for stp_move. This is not
- * done when a routine is replaced on these platforms but in this case we need to since the routines are
- * going away which will cause problems with any local variables or environment varspointing to these
- * literals.
- *
- * In this format, the only platform we support currently is Linux-x86 (i386) which uses GTM_TEXT_ALLOC()
- * to allocate special storage for it to put executable code in. We can access the storage header for
- * this storage and find out how big it is and use that information to give stp_move a good range since
- * the literal segment occurs right at the end of allocated storage (for which there is no pointer
- * in the fileheader). (Note we allow CYGWIN in here too but it has not been tested at this time)
- */
- telem = (textElem *)((char *)rtnhdr - offsetof(textElem, userStorage));
- assert(TextAllocated == telem->state);
- stp_move((char *)LNRTAB_ADR(rtnhdr) + (rtnhdr->lnrtab_len * SIZEOF(lnr_tabent)),
- (char *)rtnhdr + telem->realLen);
- /* Run the chain of old (replaced) versions freeing them first */
- for (rhdr = OLD_RHEAD_ADR(rtnhdr); rtnhdr != rhdr; rhdr = next_rhdr)
- {
- next_rhdr = (rhdtyp *)rhdr->old_rhead_ptr;
- GTM_TEXT_FREE(rhdr);
- }
- GTM_TEXT_FREE(rtnhdr);
-# endif
- }
+ zr_unlink_rtn(rtnhdr, TRUE);
}
/* All programs have been removed. If this is the "first" table allocated which cannot be removed, just reinitialize
* the table and we're done. If a new table, release it, recover the first table, initialize and we're done.
@@ -207,6 +148,6 @@ void gtm_unlink_all(void)
}
reinitialize_hashtab_objcode(&cache_table); /* Completely re-initialize the hash table */
indir_cache_mem_size = 0;
- /* Step 6: Close M code shared libraries */
+ /* Step 6: Close all M code shared libraries */
zro_shlibs_unlink_all();
}
diff --git a/sr_unix/gtmci.c b/sr_unix/gtmci.c
index d18bfdd..0bdfce2 100644
--- a/sr_unix/gtmci.c
+++ b/sr_unix/gtmci.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,8 +16,10 @@
#ifdef GTM_PTHREAD
# include <pthread.h>
#endif
+#include "gtm_stat.h"
#include "gtm_stdlib.h"
#include "gtm_string.h"
+#include "gtm_limits.h"
#include "cli.h"
#include "stringpool.h"
#include <rtnhdr.h>
@@ -32,17 +34,17 @@
#include "mv_stent.h"
#include "op.h"
#include "gtm_startup.h"
+#include "gtmsecshr.h"
#include "job_addr.h"
#include "invocation_mode.h"
#include "gtmimagename.h"
#include "gtm_exit_handler.h"
#include "gtm_savetraps.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
#include "code_address_type.h"
#include "push_lvval.h"
#include "send_msg.h"
#include "gtmmsg.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
#ifdef GTM_TRIGGER
# include "gdsroot.h"
@@ -62,11 +64,9 @@ GBLREF u_casemap_t gtm_strToTitle_ptr; /* Function pointer for gtm_strToTitle
#include "hashtab.h"
#include "hashtab_str.h"
#include "compiler.h"
-#include "gt_timer.h"
#include "have_crit.h"
#include "callg.h"
#include "min_max.h"
-#include "gtm_limits.h"
GBLREF parmblk_struct *param_list;
GBLREF stack_frame *frame_pointer;
@@ -87,6 +87,7 @@ GBLREF pthread_t gtm_main_thread_id;
GBLREF boolean_t gtm_main_thread_id_set;
#endif
GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
GTMTRIG_DBG_ONLY(GBLREF ch_ret_type (*ch_at_trigger_init)();)
LITREF gtmImageName gtmImageNames[];
@@ -96,10 +97,14 @@ error_def(ERR_CIMAXLEVELS);
error_def(ERR_CINOENTRY);
error_def(ERR_CIRCALLNAME);
error_def(ERR_CITPNESTED);
+error_def(ERR_DISTPATHMAX);
+error_def(ERR_GTMDISTUNDEF);
+error_def(ERR_GTMSECSHRPERM);
error_def(ERR_INVGTMEXIT);
error_def(ERR_JOBLABOFF);
error_def(ERR_MAXACTARG);
error_def(ERR_MAXSTRLEN);
+error_def(ERR_SYSCALL);
#define REVERT_AND_RETURN \
{ \
@@ -230,7 +235,6 @@ int gtm_cij(const char *c_rtn_name, char **arg_blob, int count, int *arg_types,
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- set_blocksig();
added = FALSE;
/* A prior invocation of gtm_exit would have set process_exiting = TRUE. Use this to disallow gtm_ci to be
* invoked after a gtm_exit
@@ -538,7 +542,6 @@ int gtm_ci_exec(const char *c_rtn_name, void *callin_handle, int populate_handle
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- set_blocksig();
VAR_COPY(var, temp_var);
added = FALSE;
/* A prior invocation of gtm_exit would have set process_exiting = TRUE. Use this to disallow gtm_ci to be
@@ -950,6 +953,10 @@ int gtm_init()
rhdtyp *base_addr;
unsigned char *transfer_addr;
char *dist;
+ int dist_len;
+ char gtmsecshr_path[GTM_PATH_MAX];
+ int gtmsecshr_path_len;
+ struct stat stat_buf;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -969,12 +976,37 @@ int gtm_init()
}
if (!gtm_startup_active)
{ /* call-in invoked from C as base. GT.M hasn't been started up yet. */
- gtm_imagetype_init(GTM_IMAGE);
- gtm_wcswidth_fnptr = gtm_wcswidth;
- gtm_env_init(); /* read in all environment variables */
+ common_startup_init(GTM_IMAGE);
err_init(stop_image_conditional_core);
UNICODE_ONLY(gtm_strToTitle_ptr = >m_strToTitle);
GTM_ICU_INIT_IF_NEEDED; /* Note: should be invoked after err_init (since it may error out) and before CLI parsing */
+ /* Ensure that $gtm_dist exists */
+ if (NULL == (dist = (char *)GETENV(GTM_DIST)))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GTMDISTUNDEF);
+ /* Ensure that $gtm_dist is non-zero and does not exceed GTM_DIST_PATH_MAX */
+ dist_len = STRLEN(dist);
+ if (!dist_len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GTMDISTUNDEF);
+ else if (GTM_DIST_PATH_MAX <= dist_len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_DISTPATHMAX, 1, GTM_DIST_PATH_MAX);
+ /* Verify that $gtm_dist/gtmsecshr is available with setuid root */
+ memcpy(gtmsecshr_path, gtm_dist, dist_len);
+ gtmsecshr_path[dist_len] = '/';
+ memcpy(gtmsecshr_path + dist_len + 1, GTMSECSHR_EXECUTABLE, STRLEN(GTMSECSHR_EXECUTABLE));
+ gtmsecshr_path_len = dist_len + 1 + STRLEN(GTMSECSHR_EXECUTABLE);
+ assertpro(GTM_PATH_MAX > gtmsecshr_path_len);
+ gtmsecshr_path[gtmsecshr_path_len] = '\0';
+ if (-1 == Stat(gtmsecshr_path, &stat_buf))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
+ LEN_AND_LIT("stat for $gtm_dist/gtmsecshr"), CALLFROM, errno);
+ /* Ensure that the call-in can execute $gtm_dist/gtmsecshr. This not sufficient for security purposes */
+ if ((ROOTUID != stat_buf.st_uid) || !(stat_buf.st_mode & S_ISUID))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GTMSECSHRPERM);
+ else
+ { /* $gtm_dist validated */
+ gtm_dist_ok_to_use = TRUE;
+ memcpy(gtm_dist, dist, dist_len);
+ }
cli_lex_setup(0, NULL);
/* Initialize msp to the maximum so if errors occur during GT.M startup below,
* the unwind logic in gtmci_ch() will get rid of the whole stack.
@@ -988,14 +1020,7 @@ int gtm_init()
invocation_mode = MUMPS_CALLIN;
init_gtm(); /* Note - this initializes fgncal_stackbase */
gtm_savetraps(); /* nullify default $ZTRAP handling */
- if (NULL != (dist = (char *)GETENV(GTM_DIST)))
- {
- assert(IS_VALID_IMAGE && (n_image_types > image_type)); /* assert image_type is initialized */
- if ((GTM_PATH_MAX - 2) <= (STRLEN(dist) + gtmImageNames[image_type].imageNameLen))
- dist = NULL;
- else
- memcpy(gtm_dist, dist, STRLEN(dist));
- }
+ assert(IS_VALID_IMAGE && (n_image_types > image_type)); /* assert image_type is initialized */
assert(gtm_startup_active);
assert(frame_pointer->flags & SFF_CI);
TREF(gtmci_nested_level) = 1;
diff --git a/sr_unix/gtmcrypt.h b/sr_unix/gtmcrypt.h
index 6789fb2..8e3085f 100644
--- a/sr_unix/gtmcrypt.h
+++ b/sr_unix/gtmcrypt.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,16 +18,17 @@
#include "deferred_signal_handler.h"
#include "wbox_test_init.h"
#include "gtmmsg.h"
-#include "error.h" /* for MAKE_MSG_WARNING macro */
-
-#define gtmcrypt_init (*gtmcrypt_init_fnptr)
-#define gtmcrypt_close (*gtmcrypt_close_fnptr)
-#define gtmcrypt_hash_gen (*gtmcrypt_hash_gen_fnptr)
-#define gtmcrypt_encrypt (*gtmcrypt_encrypt_fnptr)
-#define gtmcrypt_decrypt (*gtmcrypt_decrypt_fnptr)
-#define gtmcrypt_getkey_by_name (*gtmcrypt_getkey_by_name_fnptr)
-#define gtmcrypt_getkey_by_hash (*gtmcrypt_getkey_by_hash_fnptr)
-#define gtmcrypt_strerror (*gtmcrypt_strerror_fnptr)
+#include "error.h" /* for MAKE_MSG_WARNING macro */
+
+#define gtmcrypt_close (*gtmcrypt_close_fnptr)
+#define gtmcrypt_encrypt_decrypt (*gtmcrypt_encrypt_decrypt_fnptr)
+#define gtmcrypt_init (*gtmcrypt_init_fnptr)
+#define gtmcrypt_init_db_cipher_context_by_hash (*gtmcrypt_init_db_cipher_context_by_hash_fnptr)
+#define gtmcrypt_init_device_cipher_context_by_keyname (*gtmcrypt_init_device_cipher_context_by_keyname_fnptr)
+#define gtmcrypt_obtain_db_key_hash_by_keyname (*gtmcrypt_obtain_db_key_hash_by_keyname_fnptr)
+#define gtmcrypt_release_key (*gtmcrypt_release_key_fnptr)
+#define gtmcrypt_same_key (*gtmcrypt_same_key_fnptr)
+#define gtmcrypt_strerror (*gtmcrypt_strerror_fnptr)
/* It's important that the "gtmcrypt_interface.h" include should be *after* the above macro definitions. This way, the function
* prototypes defined in the header file will automatically be expanded to function pointers saving us the trouble of explicitly
@@ -35,11 +36,13 @@
*/
#include "gtmcrypt_interface.h"
-GBLREF boolean_t gtmcrypt_initialized;
-GBLREF mstr pvt_crypt_buf;
-GBLREF char dl_err[];
+GBLREF boolean_t gtmcrypt_initialized;
+GBLREF mstr pvt_crypt_buf;
+GBLREF char dl_err[];
+GBLREF char *gtmcrypt_badhash_size_msg;
-LITREF char gtmcrypt_repeat_msg[];
+LITREF char gtmcrypt_repeat_msg[];
+LITREF gtm_string_t null_iv;
error_def(ERR_CRYPTDLNOOPEN);
error_def(ERR_CRYPTDLNOOPEN2);
@@ -52,25 +55,25 @@ error_def(ERR_CRYPTOPFAILED);
* Error Reporting Macros *
* =====================================================================================================*/
-#define CRYPTERR_MASK 0x10000000
-#define REPEAT_MSG_MASK 0x20000000
-
-#define IS_CRYPTERR_MASK(ERRID) ((ERRID) & CRYPTERR_MASK)
-#define IS_REPEAT_MSG_MASK(ERRID) ((ERRID) & REPEAT_MSG_MASK)
-#define SET_CRYPTERR_MASK(ERRID) ((ERRID) | CRYPTERR_MASK)
-#define SET_REPEAT_MSG_MASK(ERRID) ((ERRID) | REPEAT_MSG_MASK)
-#define CLEAR_CRYPTERR_MASK(ERRID) (ERRID = ((ERRID) & ~CRYPTERR_MASK))
-#define CLEAR_REPEAT_MSG_MASK(ERRID) (ERRID = ((ERRID) & ~REPEAT_MSG_MASK))
-
-#define REALLOC_CRYPTBUF_IF_NEEDED(LEN) \
-{ \
- if (!pvt_crypt_buf.addr || (pvt_crypt_buf.len < LEN)) \
- { \
- if (pvt_crypt_buf.addr) \
- free(pvt_crypt_buf.addr); \
- pvt_crypt_buf.addr = (char *)malloc(LEN); \
- pvt_crypt_buf.len = LEN; \
- } \
+#define CRYPTERR_MASK 0x10000000
+#define REPEAT_MSG_MASK 0x20000000
+
+#define IS_CRYPTERR_MASK(ERRID) ((ERRID) & CRYPTERR_MASK)
+#define IS_REPEAT_MSG_MASK(ERRID) ((ERRID) & REPEAT_MSG_MASK)
+#define SET_CRYPTERR_MASK(ERRID) ((ERRID) | CRYPTERR_MASK)
+#define SET_REPEAT_MSG_MASK(ERRID) ((ERRID) | REPEAT_MSG_MASK)
+#define CLEAR_CRYPTERR_MASK(ERRID) (ERRID = ((ERRID) & ~CRYPTERR_MASK))
+#define CLEAR_REPEAT_MSG_MASK(ERRID) (ERRID = ((ERRID) & ~REPEAT_MSG_MASK))
+
+#define REALLOC_CRYPTBUF_IF_NEEDED(LEN) \
+{ \
+ if (!pvt_crypt_buf.addr || (pvt_crypt_buf.len < LEN)) \
+ { \
+ if (pvt_crypt_buf.addr) \
+ free(pvt_crypt_buf.addr); \
+ pvt_crypt_buf.addr = (char *)malloc(LEN); \
+ pvt_crypt_buf.len = LEN; \
+ } \
}
#define GTMCRYPT_REPORT_ERROR(ERRID, MECHANISM, LEN, PTR) \
@@ -85,30 +88,19 @@ error_def(ERR_CRYPTOPFAILED);
errptr = >mcrypt_repeat_msg[0]; \
else if ((ERR_CRYPTDLNOOPEN == errid) || (ERR_CRYPTDLNOOPEN2 == errid) \
|| (MAKE_MSG_WARNING(ERR_CRYPTDLNOOPEN2) == errid) || (MAKE_MSG_WARNING(ERR_CRYPTDLNOOPEN) == errid)) \
- { \
- errptr = (const char *) &dl_err[0]; \
- } else \
+ errptr = (const char *)&dl_err[0]; \
+ else if (ERR_CRYPTHASHGENFAILED == errid) \
+ errptr = (const char *)gtmcrypt_badhash_size_msg; \
+ else \
{ \
DEFER_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
- errptr = (const char *) gtmcrypt_strerror(); \
+ errptr = (const char *)gtmcrypt_strerror(); \
ENABLE_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
} \
CLEAR_REPEAT_MSG_MASK(errid); \
MECHANISM(VARLSTCNT(6) errid, 4, LEN, PTR, LEN_AND_STR(errptr)); \
}
-
-/* =====================================================================================================*/
-/* Utility Macros */
-/* =====================================================================================================*/
-
-/* Helper macro to package the address and length in a gtm_string_t type */
-#define PACKAGE_XCSTRING(xcstring, buf, buflen) \
-{ \
- xcstring.address = buf; \
- xcstring.length = buflen; \
-}
-
/* =====================================================================================================*/
/* GT.M Related Macros */
/* =====================================================================================================*/
@@ -133,8 +125,8 @@ error_def(ERR_CRYPTOPFAILED);
DST->is_encrypted = SRC->is_encrypted; \
} \
-/* General Note : All macros below (except GTMCRYPT_CLOSE) takes CSA as their first parameter. Currently, most macros don't
- * use CSA, but is supplied by the caller anyways in case a need arises, in the future, to reference CSA.
+/* General Note: All macros below (except GTMCRYPT_CLOSE) take CSA as their first parameter. Currently, most macros do not use CSA,
+ * but include a reference to CSA in case a need arises in the future.
*/
/* Database specific initialization - gets the encryption key corresponding to the HASH (SHA-512 currently) found in the database
@@ -143,7 +135,7 @@ error_def(ERR_CRYPTOPFAILED);
#define INIT_DB_ENCRYPTION(CSA, CSD, RC) \
{ \
RC = 0; \
- GTMCRYPT_GETKEY(CSA, CSD->encryption_hash, CSA->encr_key_handle, RC); \
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(CSA, CSD->encryption_hash, CSA->encr_key_handle, RC); \
}
/* Process specific initialization - dlopen libgtmcrypt.so and invoke gtmcrypt_init() */
@@ -155,31 +147,31 @@ error_def(ERR_CRYPTOPFAILED);
if (0 == (RC = gtmcrypt_entry())) \
{ /* dlopen succeeded */ \
DEFER_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
- gtm_status_t init_ret_status = gtmcrypt_init(IS_INTERACTIVE_MODE ? GTMCRYPT_OP_INTERACTIVE_MODE : 0); \
- ENABLE_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
- if (0 != init_ret_status) \
+ if (0 != gtmcrypt_init(IS_INTERACTIVE_MODE ? GTMCRYPT_OP_INTERACTIVE_MODE : 0)) \
RC = SET_CRYPTERR_MASK(ERR_CRYPTINIT); \
else \
- gtmcrypt_initialized = TRUE; /* No more per-process initialization needed */ \
+ gtmcrypt_initialized = TRUE; /* Intialization is done for this process. */ \
+ ENABLE_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
} else \
RC = SET_CRYPTERR_MASK(RC); \
} \
}
-/* Given a cryptographic hash (currently SHA-512), the below function retrieves a handle to the symmetric key corresponding to
- * the hash. This function is always called before attempting an encrypt or decrypt operation.
+/* Given a cryptographic hash (currently SHA-512), the below macro retrieves a handle to the symmetric key corresponding to
+ * the hash. This macro is always called before attempting an encrypt or decrypt operation.
*/
-#define GTMCRYPT_GETKEY(CSA, hash, key_handle, RC) \
+#define GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(CSA, HASH, ENCRYPT_KEY_HANDLE, RC) \
{ \
- xc_string_t xc_hash; \
- xc_status_t status; \
+ gtm_string_t hash_string; \
\
- key_handle = GTMCRYPT_INVALID_KEY_HANDLE; \
+ ENCRYPT_KEY_HANDLE = GTMCRYPT_INVALID_KEY_HANDLE; \
if (gtmcrypt_initialized) \
{ \
- PACKAGE_XCSTRING(xc_hash, hash, GTMCRYPT_HASH_LEN); \
+ assert(NULL != HASH); \
+ hash_string.length = GTMCRYPT_HASH_LEN; \
+ hash_string.address = HASH; \
DEFER_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
- if (0 != (status = gtmcrypt_getkey_by_hash(&xc_hash, &key_handle))) \
+ if (0 != gtmcrypt_init_db_cipher_context_by_hash(&(ENCRYPT_KEY_HANDLE), hash_string, null_iv)) \
RC = SET_CRYPTERR_MASK(ERR_CRYPTKEYFETCHFAILED); \
else \
RC = 0; \
@@ -188,69 +180,105 @@ error_def(ERR_CRYPTOPFAILED);
RC = SET_REPEAT_MSG_MASK((SET_CRYPTERR_MASK(ERR_CRYPTOPFAILED))); \
}
-#define GTMCRYPT_HASH_CHK(CSA, hash, RC) \
+/* Ensure that the symmetric key corresponding to the specified hash exists and that a handle is created. */
+#define GTMCRYPT_HASH_CHK(CSA, HASH, RC) \
{ \
- gtmcrypt_key_t handle; \
+ gtmcrypt_key_t handle; \
\
- GTMCRYPT_GETKEY(CSA, hash, handle, RC); \
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(CSA, HASH, handle, RC); \
}
-#define GTMCRYPT_HASH_GEN(CSA, filename, filename_len, hash, RC) \
+/* The below macro retrieves a handle to the symmetric key corresponding to the provided key name as specified in the
+ * configuration file.
+ */
+#define GTMCRYPT_INIT_CIPHER_CONTEXT(KEYNAME_LENGTH, KEYNAME, IV_LENGTH, IV, KEY_HANDLE, OPERATION, RC) \
{ \
- xc_status_t status; \
- xc_string_t xc_filename, xc_hash; \
- gtmcrypt_key_t handle; \
+ gtm_string_t keyname, iv; \
\
+ KEY_HANDLE = GTMCRYPT_INVALID_KEY_HANDLE; \
if (gtmcrypt_initialized) \
{ \
- PACKAGE_XCSTRING(xc_filename, filename, filename_len); \
- PACKAGE_XCSTRING(xc_hash, hash, GTMCRYPT_HASH_LEN); \
+ assert(NULL != KEYNAME); \
+ assert(NULL != IV); \
+ keyname.length = KEYNAME_LENGTH; \
+ keyname.address = KEYNAME; \
+ iv.length = IV_LENGTH; \
+ iv.address = IV; \
DEFER_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
- if (0 == (status = gtmcrypt_getkey_by_name(&xc_filename, &handle))) \
- { \
- if (0 == (status = gtmcrypt_hash_gen(handle, &xc_hash))) \
- { \
- memcpy(hash, xc_hash.address, GTMCRYPT_HASH_LEN); \
- RC = 0; \
- } else \
- RC = SET_CRYPTERR_MASK(ERR_CRYPTHASHGENFAILED); \
- } else \
+ if (0 != gtmcrypt_init_device_cipher_context_by_keyname(&(KEY_HANDLE), keyname, iv, OPERATION)) \
RC = SET_CRYPTERR_MASK(ERR_CRYPTKEYFETCHFAILED); \
+ else \
+ RC = 0; \
ENABLE_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
} else \
RC = SET_REPEAT_MSG_MASK((SET_CRYPTERR_MASK(ERR_CRYPTOPFAILED))); \
}
-#define GTMCRYPT_ENCRYPT(CSA, key_handle, inbuf, inbuf_len, outbuf, RC) \
+/* Safely remove the specified handle to a particular symmetric key. */
+#define GTMCRYPT_REMOVE_CIPHER_CONTEXT(KEY_HANDLE) \
+{ \
+ if (gtmcrypt_initialized) \
+ { \
+ DEFER_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
+ gtmcrypt_release_key(KEY_HANDLE); \
+ ENABLE_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
+ } \
+}
+
+/* Based on the database name (used as a key name), the below macro looks up the corresponding symmetric key and copies its hash
+ * into the passed buffer storage.
+ */
+#define GTMCRYPT_HASH_GEN(CSA, FILENAME, FILENAME_LENGTH, HASH, RC) \
{ \
- xc_string_t unencrypted_block, encrypted_block; \
- xc_status_t status; \
+ gtm_string_t filename, hash_string; \
\
- if (gtmcrypt_initialized && (GTMCRYPT_INVALID_KEY_HANDLE != key_handle)) \
+ if (gtmcrypt_initialized) \
{ \
- PACKAGE_XCSTRING(unencrypted_block, inbuf, inbuf_len); \
- PACKAGE_XCSTRING(encrypted_block, outbuf, inbuf_len); \
+ assert(NULL != FILENAME); \
+ assert(NULL != HASH); \
+ filename.length = FILENAME_LENGTH; \
+ filename.address = FILENAME; \
DEFER_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
- if (0 == (status = gtmcrypt_encrypt(key_handle, &unencrypted_block, &encrypted_block))) \
- RC = 0; \
+ if (0 != gtmcrypt_obtain_db_key_hash_by_keyname(filename, &hash_string)) \
+ RC = SET_CRYPTERR_MASK(ERR_CRYPTKEYFETCHFAILED); \
else \
- RC = SET_CRYPTERR_MASK(ERR_CRYPTOPFAILED); \
+ { \
+ if (hash_string.length != GTMCRYPT_HASH_LEN) \
+ { /* Populate the message about the bad hash size, allocating the buffer, if necessary. */ \
+ if (NULL == gtmcrypt_badhash_size_msg) \
+ gtmcrypt_badhash_size_msg = (char *)malloc(1024); \
+ SNPRINTF(gtmcrypt_badhash_size_msg, 1023, "Specified symmetric key hash has " \
+ "length %d, which is different from the expected hash length %d", \
+ hash_string.length, GTMCRYPT_HASH_LEN); \
+ RC = SET_CRYPTERR_MASK(ERR_CRYPTHASHGENFAILED); \
+ } else \
+ { /* Note that the copy is not NULL-terminated. */ \
+ memcpy(HASH, hash_string.address, hash_string.length); \
+ RC = 0; \
+ } \
+ } \
ENABLE_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
} else \
RC = SET_REPEAT_MSG_MASK((SET_CRYPTERR_MASK(ERR_CRYPTOPFAILED))); \
}
-#define GTMCRYPT_DECRYPT(CSA, key_handle, inbuf, inbuf_len, outbuf, RC) \
+/* Encrypt data with the IV reset to the initial value prior to the operation. */
+#define GTMCRYPT_ENCRYPT(CSA, KEY_HANDLE, INBUF, INBUF_LEN, OUTBUF, RC) \
+ GTMCRYPT_ENCRYPT_DECRYPT_WITH_IV(CSA, KEY_HANDLE, INBUF, INBUF_LEN, OUTBUF, GTMCRYPT_OP_ENCRYPT, GTMCRYPT_IV_RESET, RC)
+
+/* Decrypt data with the IV reset to the initial value prior to the operation. */
+#define GTMCRYPT_DECRYPT(CSA, KEY_HANDLE, INBUF, INBUF_LEN, OUTBUF, RC) \
+ GTMCRYPT_ENCRYPT_DECRYPT_WITH_IV(CSA, KEY_HANDLE, INBUF, INBUF_LEN, OUTBUF, GTMCRYPT_OP_DECRYPT, GTMCRYPT_IV_RESET, RC)
+
+/* Encrypt or decrypt data with the IV optionally set to a specified, or reset to the initial, value prior to the operation. */
+#define GTMCRYPT_ENCRYPT_DECRYPT_WITH_IV(CSA, KEY_HANDLE, INBUF, INBUF_LEN, OUTBUF, OPERATION, IV_MODE, RC) \
{ \
- xc_string_t unencrypted_block, encrypted_block; \
- xc_status_t status; \
- \
- if (gtmcrypt_initialized && (GTMCRYPT_INVALID_KEY_HANDLE != key_handle)) \
+ assert(INBUF); \
+ if (gtmcrypt_initialized && (GTMCRYPT_INVALID_KEY_HANDLE != KEY_HANDLE)) \
{ \
- PACKAGE_XCSTRING(encrypted_block, inbuf, inbuf_len); \
- PACKAGE_XCSTRING(unencrypted_block, outbuf, inbuf_len); \
DEFER_INTERRUPTS(INTRPT_IN_CRYPT_SECTION); \
- if (0 == (status = gtmcrypt_decrypt(key_handle, &encrypted_block, &unencrypted_block))) \
+ if (0 == gtmcrypt_encrypt_decrypt(KEY_HANDLE, (char *)INBUF, INBUF_LEN, (char *)OUTBUF, \
+ OPERATION, IV_MODE, null_iv)) \
RC = 0; \
else \
RC = SET_CRYPTERR_MASK(ERR_CRYPTOPFAILED); \
@@ -259,6 +287,11 @@ error_def(ERR_CRYPTOPFAILED);
RC = SET_REPEAT_MSG_MASK((SET_CRYPTERR_MASK(ERR_CRYPTOPFAILED))); \
}
+/* Check whether the specified symmetric key handles belong to the same key. */
+#define GTMCRYPT_SAME_KEY(KEY_HANDLE1, KEY_HANDLE2) \
+ gtmcrypt_same_key(KEY_HANDLE1, KEY_HANDLE2)
+
+/* Shut down the encryption for this process. */
#define GTMCRYPT_CLOSE \
{ \
if (gtmcrypt_initialized) \
diff --git a/sr_unix/gtmcrypt_dbk_ref.c b/sr_unix/gtmcrypt_dbk_ref.c
index 0fe0e8b..d599860 100644
--- a/sr_unix/gtmcrypt_dbk_ref.c
+++ b/sr_unix/gtmcrypt_dbk_ref.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,461 +18,820 @@
#include <ctype.h>
#include <assert.h>
#include <errno.h>
-#include <gpgme.h> /* gpgme functions */
-#include <gpg-error.h> /* gcry*_err_t */
+#include <gpgme.h> /* gpgme functions */
+#include <gpg-error.h> /* gcry*_err_t */
#include <libconfig.h>
#include "gtmxc_types.h"
#include "gtmcrypt_util.h"
-#include "gtmcrypt_interface.h" /* Function prototypes for gtmcrypt*.* functions */
+#include "gtmcrypt_interface.h" /* Function prototypes for gtmcrypt*.* functions */
#include "gtmcrypt_ref.h"
#include "gtmcrypt_dbk_ref.h"
#include "gtmcrypt_sym_ref.h"
#include "gtmcrypt_pk_ref.h"
-#define NEWLINE 0x0A
+#define CONFIG_FILE_UNREAD ('\0' == gc_config_filename[0])
+#define GPG_MESSAGE "Verify encrypted key file and your GNUPGHOME settings"
+#define NON_GPG_MESSAGE "Verify encryption key in configuration file pointed to by $gtmcrypt_config"
-#define PARSE_ERROR_PREFIX "Error parsing database key file"
-#define LOOKING_FOR_DB 0x1
-#define LOOKING_FOR_KEY 0x2
-
-#define PARSE_COMPLETED 0x1
-#define KEEP_GOING 0x2
+/* On certain platforms the st_mtime field of the stat structure got replaced by a timespec st_mtim field, which in turn has tv_sec
+ * and tv_nsec fields. For compatibility reasons, those platforms define an st_mtime macro which points to st_mtim.tv_sec. Whenever
+ * we detect such a situation, we define a nanosecond flavor of that macro to point to st_mtim.tv_nsec. On HPUX Itanium and older
+ * AIX boxes the stat structure simply has additional fields with the nanoseconds value, yet the names of those field are different
+ * on those two architectures, so we choose our mapping accordingly.
+ */
+#if defined st_mtime
+# define st_nmtime st_mtim.tv_nsec
+#elif defined(_AIX)
+# define st_nmtime st_mtime_n
+#elif defined(__hpux) && defined(__ia64)
+# define st_nmtime st_nmtime
+#endif
-STATICDEF int n_dbkeys;
-STATICDEF char gc_dbk_filename[GTM_PATH_MAX];
-STATICDEF gtm_dbkeys_tbl *tbl_head;
-STATICDEF config_t gtmcrypt_cfg;
-GBLDEF gtm_dbkeys_tbl **fast_lookup_entry;
-GBLDEF int gc_dbk_file_format;
+STATICDEF int n_keys; /* Count of how many keys were loaded. */
+STATICDEF char gc_config_filename[GTM_PATH_MAX]; /* Path to the configuration file. */
+STATICDEF gtm_keystore_hash_link_t *keystore_by_hash_head; /* Root of the binary search tree to look
+ * keys up by hash. */
+STATICDEF gtm_keystore_keyname_link_t *keystore_by_keyname_head; /* Root of the binary search tree to look
+ * keys up by name. */
+STATICDEF gtm_keystore_unres_keyname_link_t *keystore_by_unres_keyname_head; /* Head of the linked list holding keys of
+ * DBs with presently unresolved paths. */
+STATICDEF config_t gtmcrypt_cfg; /* Encryption configuration. */
+STATICDEF char db_real_path[GTM_PATH_MAX]; /* Array for temporary storage of DBs' real
+ * path information. */
+STATICDEF unsigned char key_hash[GTMCRYPT_HASH_LEN]; /* Array for temporary storage of keys'
+ * hashes. */
-GBLREF passwd_entry_t *gtmcrypt_pwent;
-GBLREF int gtmcrypt_init_flags;
+GBLREF passwd_entry_t *gtmcrypt_pwent;
+GBLREF int gtmcrypt_init_flags;
-/* Free up the linked list of database-symmetric key association AFTER scrubbing off the contents of the raw symmetric key and
- * its corresponding hash
+/*
+ * Find the key based on its name.
+ *
+ * Arguments: keyname Name of the key.
+ * length Length of the key name.
+ * entry Address where to place the pointer to the found key.
+ * database Flag indicating whether a database (or device) key is being searched.
+ * nulled Flag indicating whether keyname is null-terminated.
+ *
+ * Returns: 0 if the key with the specified name is found; -1 otherwise.
*/
-void gc_dbk_scrub_entries()
+int gtmcrypt_getkey_by_keyname(char *keyname, int length, gtm_keystore_t **entry, int database, int nulled)
{
- gtm_dbkeys_tbl *cur, *temp;
+ int new_db_keynames, new_dev_keynames, new_hashes, new_keynames, error;
- cur = tbl_head;
- while (NULL != cur)
- {
-# ifdef USE_GCRYPT
- if (!cur->symmetric_key_dirty)
- {
- if (cur->encr_key_handle)
- gcry_cipher_close(cur->encr_key_handle);
- if (cur->decr_key_handle)
- gcry_cipher_close(cur->decr_key_handle);
+ if (NULL == (*entry = keystore_lookup_by_keyname(keyname, length, nulled)))
+ { /* Lookup still failed. Verify if we have right permissions on GNUPGHOME or $HOME/.gnupg (if GNUPGHOME is unset).
+ * If not, then the below function will store the appropriate error message in err_string and so return -1.
+ */
+ if (0 != gc_pk_gpghome_has_permissions())
+ return -1;
+ /* Hashes are irrelevant, so using the same variable for number of both device and DB hashes. */
+ if (0 != keystore_refresh(&new_db_keynames, &new_hashes, &new_dev_keynames, &new_hashes))
+ return -1;
+ error = 0;
+ new_keynames = database ? new_db_keynames : new_dev_keynames;
+ if ((0 >= new_keynames) || ((0 < new_keynames)
+ && (NULL == (*entry = keystore_lookup_by_keyname(keyname, length, nulled)))))
+ { /* If either no keynames have been loaded, or the key is not found among those that were loaded, try the
+ * unresolved keys list.
+ */
+ if (NULL == (*entry = keystore_lookup_by_unres_keyname(keyname, &error)))
+ {
+ if (!error)
+ {
+ UPDATE_ERROR_STRING("%s " STR_ARG " missing in configuration file or does not exist",
+ (database ? "Database file" : "Keyname"), ELLIPSIZE(keyname));
+ }
+ return -1;
+ }
}
-# endif
- temp = cur->next;
- GTM_XCFILEID_FREE(cur->fileid);
- memset(cur->symmetric_key, 0, SYMMETRIC_KEY_MAX);
- memset(cur->symmetric_key_hash, 0, GTMCRYPT_HASH_LEN);
- FREE(cur);
- cur = temp;
}
- if (NULL != fast_lookup_entry)
- FREE(fast_lookup_entry);
- n_dbkeys = 0;
+ assert(NULL != *entry);
+ return 0;
}
-/* Given a fileid, containing a unique description of the dat file, the function searches for it's
- * entry in the linked list. On unsuccessful search, returns NULL.
+/*
+ * Find the key based on its hash.
+ *
+ * Arguments: hash Hash of the key.
+ * entry Address where to place the pointer to the found key.
+ *
+ * Returns: 0 if the key with the specified name is found; -1 otherwise.
*/
-gtm_dbkeys_tbl* gc_dbk_get_entry_by_fileid(gtm_fileid_ptr_t fileid)
+int gtmcrypt_getkey_by_hash(unsigned char *hash, gtm_keystore_t **entry)
{
- gtm_dbkeys_tbl *cur = tbl_head;
+ int err_caused_by_gpg;
+ char save_err[MAX_GTMCRYPT_ERR_STRLEN], hex_buff[GTMCRYPT_HASH_HEX_LEN + 1];
+ char *alert_msg;
+ int new_db_hashes, new_dev_hashes, new_keynames, new_hashes;
- while (NULL != cur)
- {
- if (!cur->fileid_dirty && (!cur->symmetric_key_dirty) && (gtm_is_file_identical(fileid, cur->fileid)))
- break;
- cur = (gtm_dbkeys_tbl *)cur->next;
+ if (NULL == (*entry = keystore_lookup_by_hash(hash)))
+ { /* Lookup still failed. Verify if we have right permissions on GNUPGHOME or $HOME/.gnupg (if GNUPGHOME is unset).
+ * If not, then the below function will store the appropriate error message in err_string and so return -1.
+ */
+ if (0 != gc_pk_gpghome_has_permissions())
+ return -1;
+ /* Keynames are irrelevant, so using the same variable for number of both device and DB keynames. */
+ if (0 != keystore_refresh(&new_keynames, &new_db_hashes, &new_keynames, &new_dev_hashes))
+ return -1;
+ new_hashes = new_db_hashes + new_dev_hashes;
+ if ((0 >= new_hashes) || ((0 < new_hashes) && (NULL == (*entry = keystore_lookup_by_hash(hash)))))
+ { /* If either no hashes have been loaded, or the key is not found among those that were loaded, try the
+ * unresolved keys list.
+ */
+ if (NULL == (*entry = keystore_lookup_by_unres_keyname_hash(hash)))
+ { /* Be specific in the error as to what hash we were trying to find. */
+ err_caused_by_gpg = ('\0' != gtmcrypt_err_string[0]);
+ alert_msg = err_caused_by_gpg ? GPG_MESSAGE : NON_GPG_MESSAGE;
+ GC_HEX(hash, hex_buff, GTMCRYPT_HASH_LEN);
+ if (err_caused_by_gpg)
+ {
+ strncpy(save_err, gtmcrypt_err_string, MAX_GTMCRYPT_ERR_STRLEN);
+ UPDATE_ERROR_STRING("Expected hash - " STR_ARG " - %s. %s",
+ ELLIPSIZE(hex_buff), save_err, alert_msg);
+ } else
+ UPDATE_ERROR_STRING("Expected hash - " STR_ARG ". %s", ELLIPSIZE(hex_buff), alert_msg);
+ return -1;
+ }
+ }
}
- return cur;
+ assert(NULL != *entry);
+ return 0;
}
-/* Given a hash, the function returns the entry in the linked list that matches with the given hash. Otherwise, NULL is returned */
-gtm_dbkeys_tbl* gc_dbk_get_entry_by_hash(gtm_string_t *hash)
+/*
+ * Helper function to perform the actual binary search of the key by its hash.
+ *
+ * Arguments: hash Hash of the key.
+ *
+ * Returns: Pointer to the key, if found; NULL otherwise.
+ */
+STATICFNDEF gtm_keystore_t *keystore_lookup_by_hash(unsigned char *hash)
{
- gtm_dbkeys_tbl *cur = tbl_head;
+ LOOKUP_KEY(keystore_by_hash_head, gtm_keystore_hash_link_t, link->key_hash, hash, GTMCRYPT_HASH_LEN, FALSE);
+}
- assert(hash && (hash->length == GTMCRYPT_HASH_LEN));
- while (NULL != cur)
- {
- if ((hash->length == GTMCRYPT_HASH_LEN) && (0 == memcmp(hash->address, cur->symmetric_key_hash, GTMCRYPT_HASH_LEN)))
- break;
- cur = cur->next;
- }
- return cur;
+/*
+ * Helper function to perform the actual binary search of the key by its name.
+ *
+ * Arguments: keyname Name of the key.
+ * length Length of the key.
+ * nulled Indicates whether keyname is null-terminated.
+ *
+ * Returns: Pointer to the key, if found; NULL otherwise.
+ */
+STATICFNDEF gtm_keystore_t *keystore_lookup_by_keyname(char *keyname, int length, int nulled)
+{
+ LOOKUP_KEY(keystore_by_keyname_head, gtm_keystore_keyname_link_t, key_name, keyname, length, !nulled);
}
-STATICFNDEF int gc_dbk_get_dbkeys_fname(char *fname, int *stat_success)
+/*
+ * Helper function to perform a linear search of the key by its name in the unresolved keys list. It attempts to resolve the real
+ * path of every node's keyname, assuming that it corresponds to a previously unresolved database name. If the path is resolved, the
+ * node's entry is used to create (as needed) new key node as well as hash- and keyname-based links to it, and the unresolved entry
+ * is removed from the list.
+ *
+ * Arguments: keyname Name of the key.
+ * error Address where to set the flag indicating whether an error was encountered.
+ *
+ * Returns: Pointer to the key, if found; NULL otherwise.
+ */
+STATICFNDEF gtm_keystore_t *keystore_lookup_by_unres_keyname(char *keyname, int *error)
{
- char *ptr;
- struct stat stat_buf;
+ gtm_keystore_unres_keyname_link_t *curr, *prev, *next;
+ gtm_keystore_t *node, *result;
+ int length;
- if (NULL != (ptr = getenv(GTM_DBKEYS)))
+ result = NULL;
+ prev = NULL;
+ curr = keystore_by_unres_keyname_head;
+ while (curr)
{
- if (0 == STRLEN(ptr))
- {
- UPDATE_ERROR_STRING(ENV_EMPTY_ERROR, GTM_DBKEYS);
- return GC_FAILURE;
- } else if (0 == stat(ptr, &stat_buf)) /* See if the environment variable points to a proper path */
+ next = curr->next;
+ if (NULL != realpath(curr->key_name, db_real_path))
+ { /* It is possible that a newly resolved realpath points to a previously seen database file, in which case we
+ * should first check whether that database has already been inserted into the tree to avoid inserting a
+ * duplicate.
+ */
+ length = strlen(db_real_path);
+ assert(length < GTM_PATH_MAX);
+ if (NULL != (node = keystore_lookup_by_keyname(db_real_path, length + 1, TRUE)))
+ { /* If we have already loaded a different key for this database, issue an error. */
+ if (memcmp(node->key_hash, curr->key_hash, GTMCRYPT_HASH_LEN))
+ {
+ *error = TRUE;
+ UPDATE_ERROR_STRING("Database file " STR_ARG " resolves to a previously seen file, but "
+ "specifies a different key", ELLIPSIZE(curr->key_name));
+ return NULL;
+ }
+ } else
+ { /* It is possible that while no key has been specified for this database, the same key has already
+ * been loaded for a different database or device, so do a lookup first.
+ */
+ if (NULL == (node = keystore_lookup_by_hash(curr->key_hash)))
+ { /* If we have not seen this hash before, create new entries. */
+ GC_ALLOCATE_KEYSTORE_ENTRY(node);
+ memcpy(node->key, curr->key, SYMMETRIC_KEY_MAX);
+ /* This should take care of assigning key_hash to the node itself. */
+ INSERT_KEY_LINK(keystore_by_hash_head, node, gtm_keystore_hash_link_t, link->key_hash,
+ curr->key_hash, GTMCRYPT_HASH_LEN, GTMCRYPT_HASH_LEN);
+ }
+ INSERT_KEY_LINK(keystore_by_keyname_head, node, gtm_keystore_keyname_link_t,
+ key_name, db_real_path, length + 1, GTM_PATH_MAX);
+ }
+ /* If we have not found a suitable node before, and this path matches, set the result to that. Do not break
+ * the loop, though, as we want to resolve as many previously unresolved paths as possible. And if it
+ * happens that some other real path matches the one we already found, we will already have it in the
+ * resolved entries' tree, so it will simply get removed from the unresolved list.
+ */
+ if ((NULL == result) && (!strcmp(keyname, db_real_path)))
+ result = node;
+ if (NULL != prev)
+ prev->next = next;
+ if (curr == keystore_by_unres_keyname_head)
+ keystore_by_unres_keyname_head = next;
+ FREE(curr);
+ } else
{
- if (S_ISDIR(stat_buf.st_mode)) /* if directory */
- {
- SNPRINTF(fname, GTM_PATH_MAX, "%s/%s", ptr, DOT_GTM_DBKEYS);
- } else if (S_ISREG(stat_buf.st_mode)) /* if file */
+ if (ENOENT == errno)
+ { /* If we still could not resolve the path, move on to the next element. */
+ prev = curr;
+ } else if (ENAMETOOLONG == errno)
{
- SNPRINTF(fname, GTM_PATH_MAX, "%s", ptr);
+ UPDATE_ERROR_STRING("Real path, or a component of the path, of the database " STR_ARG
+ " is too long", ELLIPSIZE(curr->key_name));
+ return NULL;
} else
{
- assert(FALSE);
- UPDATE_ERROR_STRING("%s is neither a directory nor a regular file", ptr);
- return GC_FAILURE;
+ UPDATE_ERROR_STRING("Could not obtain the real path of the database " STR_ARG,
+ ELLIPSIZE(curr->key_name));
+ return NULL;
}
- } else if (ENOENT == errno)
- { /* File doesn't exist */
- UPDATE_ERROR_STRING("Cannot find DB keys file - %s", ptr);
- return GC_FAILURE;
- } else
- { /* Some other error */
- UPDATE_ERROR_STRING("Cannot find DB keys file - %s. %s", ptr, strerror(errno));
- return GC_FAILURE;
}
- } else if (NULL != (ptr = getenv(HOME)))
- {
- SNPRINTF(fname, GTM_PATH_MAX, "%s/%s", ptr, DOT_GTM_DBKEYS);
- } else
- {
- UPDATE_ERROR_STRING("Neither $"GTM_DBKEYS "nor $"HOME " is defined");
- return GC_FAILURE;
+ curr = next;
}
- if (0 != stat(fname, &stat_buf))
+ return result;
+}
+
+/*
+ * Helper function to perform a linear search of the key by its hash in the unresolved keys list.
+ *
+ * Arguments: hash Hash of the key.
+ *
+ * Returns: Pointer to the key, if found; NULL otherwise.
+ */
+STATICFNDEF gtm_keystore_t *keystore_lookup_by_unres_keyname_hash(unsigned char *hash)
+{
+ gtm_keystore_unres_keyname_link_t *curr;
+ gtm_keystore_t *node, *result;
+
+ result = NULL;
+ /* Unlike with unresolved key lookups by the keyname, we will not attempt to resolve the realpath of the keyname (database
+ * file) in question. All we are interested in is a matching hash, so do a linear search thereof, and, if found, do not
+ * delete the entry, but simply create a corresponding keystore entry and a pointer from the hash-based lookup tree.
+ */
+ curr = keystore_by_unres_keyname_head;
+ while (curr)
{
- *stat_success = FALSE;
- if (ENOENT == errno)
- {
- UPDATE_ERROR_STRING("Cannot find DB keys file - %s", fname);
- } else
- {
- UPDATE_ERROR_STRING("Cannot find DB keys file - %s. %s", fname, strerror(errno));
+ if (!memcmp(curr->key_hash, hash, GTMCRYPT_HASH_LEN))
+ { /* Assumption is that a lookup by hash has already been done and not yielded any result. */
+ GC_ALLOCATE_KEYSTORE_ENTRY(node);
+ memcpy(node->key, curr->key, SYMMETRIC_KEY_MAX);
+ /* This should take care of assigning key_hash to the node itself. */
+ INSERT_KEY_LINK(keystore_by_hash_head, node, gtm_keystore_hash_link_t, link->key_hash, curr->key_hash,
+ GTMCRYPT_HASH_LEN, GTMCRYPT_HASH_LEN);
+ result = node;
+ break;
}
- return GC_FAILURE;
+ curr = curr->next;
}
- *stat_success = TRUE;
- return GC_SUCCESS;
+ return result;
}
-STATICFNDEF int gc_dbk_get_single_entry(void *handle, char **db, char **key, int n)
+/*
+ * Re-read the configuration file, if necessary, and store any previously unseen keys in memory. If the configuration file has not
+ * been modified since the last successful read, then it is not processed, and the counts for newly loaded DB and device keyname and
+ * hash entries are set to -1.
+ *
+ * Arguments: new_db_keynames Address where to place the number of added DB keyname entries.
+ * new_db_hashes Address where to place the number of added DB hash entries.
+ * new_dev_keynames Address where to place the number of added device keyname entries.
+ * new_dev_hashes Address where to place the number of added device hash entries.
+ *
+ * Returns: 0 if succeeded re-reading the configuration file; -1 otherwise.
+ */
+STATICFNDEF int keystore_refresh(int *new_db_keynames, int *new_db_hashes, int *new_dev_keynames, int *new_dev_hashes)
{
- FILE *fp;
- int current_state, space_cnt, line_type, filename_len, buflen;
- char buf[LINE_MAX];
- static int line_no;
- config_setting_t *db_setting, *elem;
-
- /* The caller makes sure that the file format at this point is either the old $gtm_dbkeys flat file format or the new
- * libconfig file format. Assert accordingly. In PRO, if the file format is neither, we fall-through anyways and attempt
- * to parse the flat-file provides an appropriate error message to the user.
- */
- assert((LIBCONFIG_FILE_FORMAT == gc_dbk_file_format) || (DBKEYS_FILE_FORMAT == gc_dbk_file_format));
- if (LIBCONFIG_FILE_FORMAT == gc_dbk_file_format)
- {
- db_setting = (config_setting_t *)handle;
- if (n + 1 == config_setting_length(db_setting))
- return PARSE_COMPLETED;
- if (NULL != (elem = config_setting_get_elem(db_setting, n)))
+ int n_mappings, just_read;
+ char *config_env;
+ struct stat stat_info;
+ static long last_modified_s, last_modified_ns;
+ gtm_keystore_t *node;
+
+ just_read = FALSE;
+ if (CONFIG_FILE_UNREAD)
+ { /* First, make sure we have a proper environment varible and a regular configuration file. */
+ if (NULL != (config_env = getenv("gtmcrypt_config")))
{
- if (!config_setting_lookup_string(elem, "dat", (const char **)db))
+ if (0 == strlen(config_env))
{
- UPDATE_ERROR_STRING("In config file %s, entry# %d corresponding to database.keys "
- "does not have a `dat' item", gc_dbk_filename, n + 1);
+ UPDATE_ERROR_STRING(ENV_EMPTY_ERROR, "gtmcrypt_config");
return -1;
}
-
- if (!config_setting_lookup_string(elem, "key", (const char **)key))
+ if (0 != stat(config_env, &stat_info))
{
- UPDATE_ERROR_STRING("In config file %s, entry# %d corresponding to database.keys "
- "does not have a `key' item", gc_dbk_filename, n + 1);
+ UPDATE_ERROR_STRING("Cannot stat configuration file: " STR_ARG ". %s", ELLIPSIZE(config_env),
+ strerror(errno));
return -1;
}
- return KEEP_GOING;
- }
- assert(FALSE); /* We should never reach here as that would mean we couldn't find the nth entry in database.keys. */
- }
- /* Fall-through: Old $gtm_dbkeys flat file format. Read a single pair of database-key entry. */
- fp = (FILE *)handle;
- current_state = LOOKING_FOR_DB;
- while (!feof(fp))
- {
- if (NULL == fgets(buf, LINE_MAX, fp))
- break;
- line_no++;
- buflen = STRLEN(buf);
- if (NEWLINE != buf[buflen - 1])
- { /* Last character in the buffer is not a newline implying that the line contains more than LINE_MAX
- * characters.
- */
- UPDATE_ERROR_STRING("%s. Entry at line: %d longer than %ld characters", PARSE_ERROR_PREFIX, line_no,
- LINE_MAX);
- return -1;
- }
- buf[--buflen] = '\0'; /* strip off the newline at the end */
- for (space_cnt = 0; isspace(buf[space_cnt]); space_cnt++) /* BYPASSOK -- cannot use ISSPACE */
- ;
- assert(space_cnt <= buflen);
- if ((0 == space_cnt) && ('\0' != buf[0]))
- {
- if (0 == memcmp(buf, DATABASE_LINE_INDICATOR, DATABASE_LINE_INDICATOR_SIZE))
- {
- filename_len = buflen - DATABASE_LINE_INDICATOR_SIZE;
- line_type = DATABASE_LINE_INFO;
- } else if (0 == memcmp(buf, SYMMETRIC_KEY_LINE_INDICATOR, SYMMETRIC_KEY_LINE_INDICATOR_SIZE))
+ if (!S_ISREG(stat_info.st_mode))
{
- filename_len = buflen - SYMMETRIC_KEY_LINE_INDICATOR_SIZE;
- line_type = SYMMETRIC_KEY_LINE_INFO;
- } else
- line_type = -1;
- } else if (space_cnt < buflen)
- line_type = -1; /* line doesn't consist entirely of spaces (but only has leading spaces) */
- else
- continue; /* skip this line as it consists entirely of spaces -- blank line */
- switch (line_type)
- {
- case DATABASE_LINE_INFO:
- if (LOOKING_FOR_KEY == current_state)
- {
- UPDATE_ERROR_STRING("%s. At line %d: Found DAT entry, expecting KEY entry",
- PARSE_ERROR_PREFIX, line_no);
- return -1;
- }
- memcpy(*db, &buf[DATABASE_LINE_INDICATOR_SIZE], filename_len + 1);
- assert('\0' == *(*db + filename_len));
- current_state = LOOKING_FOR_KEY;
- break;
-
- case SYMMETRIC_KEY_LINE_INFO:
- if (LOOKING_FOR_DB == current_state)
- {
- UPDATE_ERROR_STRING("%s. At line %d: Found KEY entry, expecting DAT entry",
- PARSE_ERROR_PREFIX, line_no);
- return -1;
- }
- memcpy(*key, &buf[SYMMETRIC_KEY_LINE_INDICATOR_SIZE], filename_len + 1);
- assert('\0' == *(*key + filename_len));
- current_state = LOOKING_FOR_DB;
- return KEEP_GOING; /* Done reading a single entry. */
-
- default:
- UPDATE_ERROR_STRING("%s. At line %d: %s does not start with 'dat '/'key '", PARSE_ERROR_PREFIX,
- line_no, buf);
+ UPDATE_ERROR_STRING("Configuration file " STR_ARG " is not a regular file", ELLIPSIZE(config_env));
return -1;
+ }
+ } else
+ {
+ UPDATE_ERROR_STRING(ENV_UNDEF_ERROR, "gtmcrypt_config");
+ return -1;
}
+ /* The gtmcrypt_config variable is defined and accessible. Copy it to a global for future references. */
+ strncpy(gc_config_filename, config_env, GTM_PATH_MAX);
+ just_read = TRUE;
}
- if (!feof(fp))
+ assert(!CONFIG_FILE_UNREAD);
+ /* Stat the file if not done already, so that we can get the last modified date. */
+ if ((!just_read) && (0 != stat(gc_config_filename, &stat_info)))
{
- UPDATE_ERROR_STRING("Error while reading from database key file. %s", strerror(errno));
+ UPDATE_ERROR_STRING("Cannot stat configuration file " STR_ARG ". %s", ELLIPSIZE(gc_config_filename),
+ strerror(errno));
return -1;
- } else if (0 == line_no)
+ }
+ /* If the config file has not been modified since the last time we checked, return right away. */
+ if ((last_modified_s > (long)stat_info.st_mtime)
+ || ((last_modified_s == (long)stat_info.st_mtime)
+ && (last_modified_ns >= (long)stat_info.st_nmtime)))
{
- UPDATE_ERROR_STRING("%s. No entries found in DB keys file.", PARSE_ERROR_PREFIX);
+ *new_db_keynames = *new_db_hashes = *new_dev_keynames = *new_dev_hashes = -1;
+ return 0;
+ }
+ /* File has been modified, so re-read it. */
+ if (!config_read_file(>mcrypt_cfg, gc_config_filename))
+ {
+ UPDATE_ERROR_STRING("Cannot read config file " STR_ARG ". At line# %d - %s", ELLIPSIZE(gc_config_filename),
+ config_error_line(>mcrypt_cfg), config_error_text(>mcrypt_cfg))
return -1;
- } else if (LOOKING_FOR_KEY == current_state)
+ }
+ /* Check and update the value of gtm_passwd if it has changed since we last checked. This way, if the user had originally
+ * entered a wrong password, but later changed the value (possible in MUMPS using external call), we read the up-to-date
+ * value instead of issuing an error.
+ */
+ if (0 != gc_update_passwd(GTM_PASSWD_ENV, >mcrypt_pwent, GTMCRYPT_DEFAULT_PASSWD_PROMPT,
+ GTMCRYPT_OP_INTERACTIVE_MODE & gtmcrypt_init_flags))
{
- UPDATE_ERROR_STRING("%s. No matching KEY entry found for DAT entry at line: %d", PARSE_ERROR_PREFIX, line_no);
return -1;
}
- return PARSE_COMPLETED;
+ /* Clear the entire unresolved keys list because it will be rebuilt. */
+ REMOVE_UNRESOLVED_KEY_LINKS;
+ /* The configuration file has two sections that we are interested in. The "database" section which contains a mapping of
+ * the database filenames and their corresponding key files and the "files" section which contains a mapping of regular
+ * files (read and written by GT.M) and their corresponding key files. Read both the sections to create the key and
+ * encryption / decryption structures as outlined in gtmcrypt_dbk_ref.h.
+ */
+ *new_db_keynames = *new_db_hashes = *new_dev_keynames = *new_dev_hashes = 0;
+ if (-1 == read_database_section(>mcrypt_cfg, &n_mappings, new_db_keynames, new_db_hashes))
+ return -1;
+ n_keys += n_mappings;
+ if (-1 == read_files_section(>mcrypt_cfg, &n_mappings, new_dev_keynames, new_dev_hashes))
+ return -1;
+ n_keys += n_mappings;
+ /* If we update the modified date before we go through the configuration and validate everything in it, any error might
+ * cause the unresolved list to not be built and configuration file to not subsequently be reread.
+ */
+ last_modified_s = (long)stat_info.st_mtime;
+ last_modified_ns = (long)stat_info.st_nmtime;
+ assert((0 == n_keys) ||
+ ((NULL != keystore_by_hash_head) && (NULL != keystore_by_keyname_head)) ||
+ (NULL != keystore_by_unres_keyname_head));
+ if (0 == n_keys)
+ {
+ UPDATE_ERROR_STRING("Configuration file " STR_ARG " contains neither 'database.keys' section nor 'files' section, "
+ "or both sections are empty.", ELLIPSIZE(gc_config_filename));
+ return -1;
+ }
+ return 0;
}
-int gc_dbk_init_dbkeys_tbl()
+/*
+ * Process the 'files' section of the configuration file, storing any previously unseen key.
+ *
+ * Arguments: cfgp Pointer to the configuration object as populated by libconfig.
+ * n_mappings Pointer to a variable where to place the number of key entries found in the file.
+ * new_keynames Pointer to a variable where to place the number of key references by keyname added to storage.
+ * new_hashes Pointer to a variable where to place the number of key references by hash added to storage.
+ *
+ * Returns: 0 if successfully processed the 'files' section; -1 otherwise.
+ */
+STATICFNDEF int read_files_section(config_t *cfgp, int *n_mappings, int *new_keynames, int *new_hashes)
{
- FILE *fp;
- void *handle;
- int count, status, ret, stat_success;
- char err[MAX_GTMCRYPT_ERR_STRLEN], *db, *key, db_fname[GTM_PATH_MAX], key_fname[GTM_PATH_MAX];
- char *config_env;
- struct stat stat_info;
- static time_t last_modified;
- config_setting_t *setting;
- gtm_dbkeys_tbl *node;
+ int i, length, lcl_n_maps, raw_key_length;
+ config_setting_t *setting, *elem;
+ gtm_keystore_t *node;
+ char *name, *key;
+ unsigned char raw_key[SYMMETRIC_KEY_MAX];
- if (INVALID_FILE_FORMAT == gc_dbk_file_format)
- { /* Decide which file format to use: Old format ($gtm_dbkeys) or the new format ($gtmcrypt_config). */
- if ((GC_SUCCESS != gc_dbk_get_dbkeys_fname(gc_dbk_filename, &stat_success)) || !stat_success)
- {
- if (NULL != (config_env = getenv("gtmcrypt_config")))
- {
- strncpy(err, gtmcrypt_err_string, MAX_GTMCRYPT_ERR_STRLEN);
- if (0 != stat(config_env, &stat_info))
- {
- UPDATE_ERROR_STRING("Failed to open $gtm_dbkeys. Reason: %s; attempt to read alternate "
- "config file %s failed as well. Reason: %s", err, config_env,
- strerror(errno));
- return GC_FAILURE;
- }
- } else
- return GC_FAILURE; /* Error string is already updated in gc_dbk_get_dbkeys_fname. */
- strncpy(gc_dbk_filename, config_env, GTM_PATH_MAX);
- gc_dbk_file_format = LIBCONFIG_FILE_FORMAT;
- } else
- gc_dbk_file_format = DBKEYS_FILE_FORMAT;
- }
- assert('\0' != gc_dbk_filename[0]);
- if (0 != stat(gc_dbk_filename, &stat_info))
+ *new_keynames = *new_hashes = 0;
+ if (NULL == (setting = config_lookup(cfgp, "files")))
{
- assert(FALSE);
- UPDATE_ERROR_STRING("Cannot stat %s file %s. %s", DBKEYS_FILE_FORMAT == gc_dbk_file_format ? "DB keys" : "config",
- gc_dbk_filename, strerror(errno));
- return GC_FAILURE;
+ *n_mappings = 0;
+ return 0;
}
- if (last_modified == stat_info.st_mtime)
- return GC_SUCCESS; /* Nothing changed since we last read it. So, return success. */
- handle = NULL;
- if (DBKEYS_FILE_FORMAT == gc_dbk_file_format)
+ lcl_n_maps = config_setting_length(setting);
+ for (i = 0; i < lcl_n_maps; i++)
{
- if (NULL == (fp = fopen(gc_dbk_filename, "r")))
+ elem = config_setting_get_elem(setting, i);
+ assert(NULL != elem);
+ assert(CONFIG_TYPE_STRING == config_setting_type(elem));
+ if (NULL == (name = config_setting_name(elem)))
{
- UPDATE_ERROR_STRING("Cannot open DB keys file - %s. %s", gc_dbk_filename, strerror(errno));
- return GC_FAILURE;
+ UPDATE_ERROR_STRING("In config file " STR_ARG
+ ", entry #%d corresponding to 'files' does not have a key attribute",
+ ELLIPSIZE(gc_config_filename), i + 1);
+ return -1;
}
- handle = fp;
- } else
- {
- if (!config_read_file(>mcrypt_cfg, gc_dbk_filename))
+ /* Length should be under GTM_PATH_MAX because that is the size of the array where the name of a key is stored. */
+ length = strlen(name);
+ if (GTM_PATH_MAX <= length)
+ {
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", entry #%d's field length exceeds %d",
+ ELLIPSIZE(gc_config_filename), i + 1, GTM_PATH_MAX - 1);
+ return -1;
+ }
+ if (NULL == (key = (char *)config_setting_get_string(elem)))
+ {
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", cannot find the value corresponding to 'files.%s'",
+ ELLIPSIZE(gc_config_filename), name);
+ return -1;
+ }
+ /* Now that we have the name of the symmetric key file, try to decrypt it. If gc_pk_get_decrypted_key returns a
+ * non-zero status, it should have already populated the error string.
+ */
+ if (0 != gc_pk_get_decrypted_key(key, raw_key, &raw_key_length))
+ return -1;
+ if (0 == raw_key_length)
+ {
+ UPDATE_ERROR_STRING("Symmetric key " STR_ARG " found to be empty", ELLIPSIZE(key));
+ return -1;
+ }
+ /* We expect a symmetric key within a certain length. */
+ assert(SYMMETRIC_KEY_MAX >= raw_key_length);
+ /* For most key operations we need a hash, so compute it now. */
+ GC_PK_COMPUTE_HASH(key_hash, raw_key);
+ /* Make sure we have not previously specified a different key for the same device. */
+ if (NULL != (node = keystore_lookup_by_keyname(name, length + 1, TRUE)))
{
- UPDATE_ERROR_STRING("Cannot read config file %s. At line# %d - %s", gc_dbk_filename,
- config_error_line(>mcrypt_cfg), config_error_text(>mcrypt_cfg))
- return GC_FAILURE;
+ if (memcmp(node->key_hash, key_hash, GTMCRYPT_HASH_LEN))
+ {
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", the key 'files." STR_ARG
+ "' has already been seen, but specifies a different key",
+ ELLIPSIZE(gc_config_filename), ELLIPSIZE(name));
+ return -1;
+ } else
+ continue;
}
- if (NULL == (setting = config_lookup(>mcrypt_cfg, "database.keys")))
+ /* It is possible that while no key has been specified under this name, the same key has already been loaded
+ * for a different database or device, so look up the key by hash to avoid duplicates.
+ */
+ if (NULL == (node = keystore_lookup_by_hash(key_hash)))
{
- UPDATE_ERROR_STRING("Failed to lookup database.keys in config file %s", gc_dbk_filename);
- return GC_FAILURE;
+ GC_ALLOCATE_KEYSTORE_ENTRY(node);
+ /* WARNING: Not doing a memset here because raw_key comes padded with NULLs from gc_pk_get_decrypted_key. */
+ memcpy(node->key, raw_key, SYMMETRIC_KEY_MAX);
+ /* This should take care of assigning key_hash to the node itself. */
+ INSERT_KEY_LINK(keystore_by_hash_head, node, gtm_keystore_hash_link_t, link->key_hash, key_hash,
+ GTMCRYPT_HASH_LEN, GTMCRYPT_HASH_LEN);
+ (*new_hashes)++;
}
- handle = setting;
+ INSERT_KEY_LINK(keystore_by_keyname_head, node, gtm_keystore_keyname_link_t,
+ key_name, name, length + 1, GTM_PATH_MAX);
+ (*new_keynames)++;
}
- assert(NULL != handle);
- if (tbl_head)
+ *n_mappings = lcl_n_maps;
+ return 0;
+}
+
+/*
+ * Process the 'database' section of the configuration file, storing any previously unseen key.
+ *
+ * Arguments: cfgp Pointer to the configuration object as populated by libconfig.
+ * n_mappings Pointer to a variable where to place the number of key entries found in the file.
+ * new_keynames Pointer to a variable where to place the number of key references by keyname added to storage.
+ * new_hashes Pointer to a variable where to place the number of key references by hash added to storage.
+ *
+ * Returns: 0 if successfully processed the 'database' section; -1 otherwise.
+ */
+STATICFNDEF int read_database_section(config_t *cfgp, int *n_mappings, int *new_keynames, int *new_hashes)
+{
+ int i, length, lcl_n_maps, raw_key_length;
+ int defer, key_found_by_filename;
+ config_setting_t *setting, *elem;
+ gtm_keystore_t *node;
+ char *name, *key;
+ unsigned char raw_key[SYMMETRIC_KEY_MAX];
+
+ *new_keynames = *new_hashes = 0;
+ if (NULL == (setting = config_lookup(cfgp, "database.keys")))
{
- gc_dbk_scrub_entries(); /* free up the existing linked list as we are about to create a fresh one */
- tbl_head = NULL;
+ *n_mappings = 0;
+ return 0;
}
- db = &db_fname[0];
- key = &key_fname[0];
- while (KEEP_GOING == (status = gc_dbk_get_single_entry(handle, &db, &key, n_dbkeys)))
+ lcl_n_maps = config_setting_length(setting);
+ /* The following code makes sure that having an empty last entry in the database section is not required and does not cause
+ * errors, as GTM-7948's original implementation would have it.
+ */
+ if (lcl_n_maps > 1)
{
- assert('\0' == db[strlen(db)]);
- assert('\0' == key[strlen(key)]);
- GC_ALLOCATE_TBL_ENTRY(node);
- strncpy(node->database_fn, db, GTM_PATH_MAX);
- strncpy(node->symmetric_key_fn, key, GTM_PATH_MAX);
- node->next = tbl_head;
- tbl_head = node;
- n_dbkeys++;
+ elem = config_setting_get_elem(setting, lcl_n_maps - 1);
+ if (0 == config_setting_length(elem))
+ {
+ config_setting_remove_elem(setting, lcl_n_maps - 1);
+ lcl_n_maps--;
+ }
}
- if (PARSE_COMPLETED == status)
+ for (i = 0; i < lcl_n_maps; i++)
{
- fast_lookup_entry = (gtm_dbkeys_tbl **)MALLOC((SIZEOF(fast_lookup_entry) * n_dbkeys));
- node = tbl_head;
- for (count = 0, node = tbl_head; NULL != node; node = node->next, count++)
+ elem = config_setting_get_elem(setting, i);
+ assert(NULL != elem);
+ if (!config_setting_lookup_string(elem, "dat", (const char **)&name))
{
- node->index = count;
- fast_lookup_entry[count] = node;
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", entry #%d corresponding to "
+ "database.keys does not have a 'dat' item", ELLIPSIZE(gc_config_filename), i + 1);
+ return -1;
}
- assert(count == n_dbkeys);
- ret = 0;
- } else
- ret = -1;
- if (DBKEYS_FILE_FORMAT == gc_dbk_file_format)
- fclose(fp);
- else
- config_destroy(>mcrypt_cfg);
- return ret;
-}
-
-int gc_dbk_fill_symkey_hash(gtm_fileid_ptr_t req_fileid, char *req_hash)
-{
- gtm_dbkeys_tbl *cur;
- int status, concerns_current_file, skip_entry, plain_text_length;
- gtm_fileid_ptr_t db_fileid;
- gtm_string_t filename;
-
- cur = tbl_head;
- while (NULL != cur)
- {
- db_fileid = NULL;
- if (cur->fileid_dirty)
+ /* Length should be under GTM_PATH_MAX because that is the size of the array where the name of a key is stored. */
+ if (GTM_PATH_MAX <= strlen(name))
{
- filename.length = cur->database_fn_len;
- filename.address = cur->database_fn;
- if (TRUE == GTM_FILENAME_TO_ID(&filename, &db_fileid))
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", entry #%d's database file name exceeds %d",
+ ELLIPSIZE(gc_config_filename), i + 1, GTM_PATH_MAX - 1);
+ return -1;
+ }
+ /* Database might not exist yet, in which case set the flag to place the entry in unresolved databases list and not
+ * error out.
+ */
+ if (NULL == realpath(name, db_real_path))
+ {
+ if (ENOENT == errno)
+ defer = 1;
+ else if (ENAMETOOLONG == errno)
+ {
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", the real path, or a component of the path, of the "
+ "database in entry #%d of database.keys section is too long",
+ ELLIPSIZE(gc_config_filename), i + 1);
+ return -1;
+ } else
{
- cur->fileid_dirty = FALSE;
- cur->fileid = db_fileid;
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", could not obtain the real path of the database in "
+ "entry #%d of database.keys section", ELLIPSIZE(gc_config_filename), i + 1);
+ return -1;
}
+ } else
+ defer = 0;
+ if (!config_setting_lookup_string(elem, "key", (const char **)&key))
+ {
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", entry #%d corresponding to "
+ "database.keys does not have a 'key' item", ELLIPSIZE(gc_config_filename), i + 1);
+ return -1;
}
- if (cur->symmetric_key_dirty) /* Need to fill sym key value */
+ /* Now that we have the name of the symmetric key file, try to decrypt it. If gc_pk_get_decrypted_key returns a
+ * non-zero status, it should have already populated the error string.
+ */
+ if (0 != gc_pk_get_decrypted_key(key, raw_key, &raw_key_length))
+ return -1;
+ if (0 == raw_key_length)
{
- skip_entry = FALSE;
- /* Check & update the value of $gtm_passwd if it changed since we last checked. This way, if the user
- * had originally entered a wrong password, but later changed the value (possible in MUMPS using external
- * call), we read the up-to-date value instead of issuing an error.
- */
- if (0 != gc_update_passwd(GTM_PASSWD_ENV, >mcrypt_pwent, GTMCRYPT_DEFAULT_PASSWD_PROMPT,
- GTMCRYPT_OP_INTERACTIVE_MODE & gtmcrypt_init_flags))
+ UPDATE_ERROR_STRING("Symmetric key " STR_ARG " found to be empty", ELLIPSIZE(key));
+ return -1;
+ }
+ /* We expect a symmetric key within a certain length. */
+ assert(SYMMETRIC_KEY_MAX >= raw_key_length);
+ /* For most key operations we need a hash, so compute it now. */
+ GC_PK_COMPUTE_HASH(key_hash, raw_key);
+ /* Depending on whether we are deferring the key storage and error processing, either verify that the key is unique
+ * and create proper references or place it in the unresolved keys list.
+ */
+ if (!defer)
+ {
+ length = strlen(db_real_path);
+ assert(length < GTM_PATH_MAX);
+ /* Make sure we have not previously specified a different key for the same database. */
+ if (NULL != (node = keystore_lookup_by_keyname(db_real_path, length + 1, TRUE)))
{
- return GC_FAILURE;
+ if (memcmp(node->key_hash, key_hash, GTMCRYPT_HASH_LEN))
+ {
+ UPDATE_ERROR_STRING("In config file " STR_ARG ", the database file in entry #%d resolves "
+ "to a previously seen file, but specifies a different key",
+ ELLIPSIZE(gc_config_filename), i + 1);
+ return -1;
+ } else
+ continue;
}
- status = gc_pk_get_decrypted_key(cur->symmetric_key_fn, cur->symmetric_key, &plain_text_length);
- concerns_current_file = (NULL != req_fileid && (GTM_IS_FILE_IDENTICAL(cur->fileid, req_fileid)));
- if (0 != status)
+ /* It is possible that while no key has been specified for this database, the same key has already been
+ * loaded for a different database or device, so look up the key by hash to avoid duplicates.
+ */
+ if (NULL == (node = keystore_lookup_by_hash(key_hash)))
{
- /* If we failed because of wrong we password OR we are processing an entry that concerns the file
- * for which we are called for, don't continue any further
+ GC_ALLOCATE_KEYSTORE_ENTRY(node);
+ /* WARNING: Not doing a memset here because raw_key comes padded with NULLs from
+ * gc_pk_get_decrypted_key.
*/
- if ((GPG_ERR_BAD_PASSPHRASE == status) || concerns_current_file)
- return GC_FAILURE;
- skip_entry = TRUE;
- } else if (0 == plain_text_length)
- { /* It's possible that the decryption didn't encounter error but the plain text length is 0 */
- if (concerns_current_file)
- {
- UPDATE_ERROR_STRING("Symmetric key %s found to be empty", cur->symmetric_key_fn);
- return GC_FAILURE;
- }
- skip_entry = TRUE;
- }
- if (!skip_entry)
- { /* Everything is fine, compute the hash for the key */
- GC_PK_COMPUTE_HASH(cur->symmetric_key_hash, cur->symmetric_key);
- if (0 != gc_sym_create_key_handles(cur))
- return -1;
- cur->symmetric_key_dirty = FALSE;
- if (concerns_current_file
- || (NULL != req_hash && (0 == memcmp(cur->symmetric_key_hash, req_hash, GTMCRYPT_HASH_LEN))))
- { /* Processed the entry for which the function was called or found a matching hash. Return */
- return GC_SUCCESS;
- }
+ memcpy(node->key, raw_key, SYMMETRIC_KEY_MAX);
+ /* This should take care of assigning key_hash to the node itself. */
+ INSERT_KEY_LINK(keystore_by_hash_head, node, gtm_keystore_hash_link_t, link->key_hash, key_hash,
+ GTMCRYPT_HASH_LEN, GTMCRYPT_HASH_LEN);
+ (*new_hashes)++;
}
+ INSERT_KEY_LINK(keystore_by_keyname_head, node, gtm_keystore_keyname_link_t, key_name, db_real_path,
+ length + 1, GTM_PATH_MAX);
+ (*new_keynames)++;
+ } else
+ { /* WARNING: Not passing the raw key length here because raw_key comes padded with NULLs from
+ * gc_pk_get_decrypted_key and there is no need to know its length.
+ */
+ INSERT_UNRESOLVED_KEY_LINK(raw_key, key_hash, name);
}
- cur = cur->next;
}
- return GC_SUCCESS;
+ *n_mappings = lcl_n_maps;
+ return 0;
}
-void gc_dbk_get_hash(gtm_dbkeys_tbl *entry, gtm_string_t *hash)
+/*
+ * Create new encryption / decryption state object with the specified IV.
+ *
+ * Arguments: entry Pointer to the key structure to which the encryption / decryption state object will be assigned.
+ * iv Initialization vector to use.
+ * length Length of the initialization vector.
+ * action 1 for encryption, 0 for decryption.
+ *
+ * Returns: 0 if successfully created a new encryption / decryption state object; -1 otherwise.
+ */
+int keystore_new_cipher_ctx(gtm_keystore_t *entry, char *iv, int length, int action)
+{
+ int rv;
+ crypt_key_t handle;
+ gtm_cipher_ctx_t *ctx;
+ unsigned char iv_array[GTMCRYPT_IV_LEN];
+
+ memset(iv_array, 0, GTMCRYPT_IV_LEN);
+ memcpy(iv_array, iv, length);
+ if (0 != (rv = gc_sym_create_cipher_handle(entry->key, iv_array, &handle, action)))
+ return rv;
+ ctx = MALLOC(SIZEOF(gtm_cipher_ctx_t));
+ ctx->store = entry;
+ ctx->handle = handle;
+ memcpy(ctx->iv, iv_array, GTMCRYPT_IV_LEN);
+ if (!entry->cipher_head)
+ {
+ ctx->next = ctx->prev = NULL;
+ } else
+ {
+ ctx->next = entry->cipher_head;
+ ctx->prev = NULL;
+ entry->cipher_head->prev = ctx;
+ }
+ entry->cipher_head = ctx;
+ return 0;
+}
+
+/*
+ * Remove an encryption / decryption state object.
+ *
+ * Arguments: ctx Pointer to the encryption / decryption state object to remove.
+ */
+void keystore_remove_cipher_ctx(gtm_cipher_ctx_t *ctx)
{
- assert(hash->address);
- assert(NULL != entry);
- memcpy(hash->address, entry->symmetric_key_hash, GTMCRYPT_HASH_LEN);
- hash->length = GTMCRYPT_HASH_LEN;
+ gtm_cipher_ctx_t *next, *prev;
+
+ assert(NULL != ctx);
+ gc_sym_destroy_cipher_handle(ctx->handle);
+ next = ctx->next;
+ prev = ctx->prev;
+ if (NULL != prev)
+ prev->next = next;
+ if (NULL != next)
+ next->prev = prev;
+ if (ctx->store->cipher_head == ctx)
+ ctx->store->cipher_head = next;
+ if (ctx->store->db_cipher_entry == ctx)
+ ctx->store->db_cipher_entry = NULL;
+ FREE(ctx);
+}
+
+/*
+ * Clean up all key and encryption / decryption state contexts.
+ */
+void gtm_keystore_cleanup_all()
+{
+ if (NULL != keystore_by_hash_head)
+ {
+ gtm_keystore_cleanup_hash_tree(keystore_by_hash_head);
+ keystore_by_hash_head = NULL;
+ }
+ if (NULL != keystore_by_keyname_head)
+ {
+ gtm_keystore_cleanup_keyname_tree(keystore_by_keyname_head);
+ keystore_by_keyname_head = NULL;
+ }
+ if (NULL != keystore_by_unres_keyname_head)
+ {
+ gtm_keystore_cleanup_unres_keyname_list(keystore_by_unres_keyname_head);
+ keystore_by_unres_keyname_head = NULL;
+ }
+}
+
+/*
+ * Clean up a particular key object and all its encryption / decryption state objects.
+ *
+ * Arguments: node Key object to clean.
+ */
+STATICFNDEF void gtm_keystore_cleanup_node(gtm_keystore_t *node)
+{
+ gtm_cipher_ctx_t *curr, *temp;
+
+ curr = node->cipher_head;
+ while (NULL != curr)
+ {
+ temp = curr->next;
+ gc_sym_destroy_cipher_handle(curr->handle);
+ FREE(curr);
+ curr = temp;
+ }
+ memset(node->key, 0, SYMMETRIC_KEY_MAX);
+ memset(node->key_hash, 0, GTMCRYPT_HASH_LEN);
+ FREE(node);
+}
+
+/*
+ * Clean up (recursively) a binary search tree for looking up keys by their hashes.
+ *
+ * Arguments: entry Pointer to the node from which to descend for cleaning.
+ */
+STATICFNDEF void gtm_keystore_cleanup_hash_tree(gtm_keystore_hash_link_t *entry)
+{
+ gtm_keystore_hash_link_t *curr;
+
+ while (TRUE)
+ {
+ if (NULL != entry->left)
+ gtm_keystore_cleanup_hash_tree(entry->left);
+ gtm_keystore_cleanup_node(entry->link);
+ curr = entry;
+ if (NULL != entry->right)
+ entry = entry->right;
+ else
+ break;
+ FREE(curr);
+ }
+}
+
+/*
+ * Clean up (recursively) a binary search tree for looking up keys by their names.
+ *
+ * Arguments: entry Pointer to the node from which to descend for cleaning.
+ */
+STATICFNDEF void gtm_keystore_cleanup_keyname_tree(gtm_keystore_keyname_link_t *entry)
+{
+ gtm_keystore_keyname_link_t *curr;
+
+ while (TRUE)
+ {
+ if (NULL != entry->left)
+ gtm_keystore_cleanup_keyname_tree(entry->left);
+ curr = entry;
+ if (NULL != entry->right)
+ entry = entry->right;
+ else
+ break;
+ FREE(curr);
+ }
+}
+
+/*
+ * Clean up (linearly) an unresolved keys list.
+ *
+ * Arguments: entry Pointer to the node from which to continue cleaning.
+ */
+STATICFNDEF void gtm_keystore_cleanup_unres_keyname_list(gtm_keystore_unres_keyname_link_t *entry)
+{
+ gtm_keystore_unres_keyname_link_t *curr;
+
+ while (NULL != entry)
+ {
+ curr = entry;
+ memset(entry->key, 0, SYMMETRIC_KEY_MAX);
+ memset(entry->key_hash, 0, GTMCRYPT_HASH_LEN);
+ entry = entry->next;
+ FREE(curr);
+ }
}
diff --git a/sr_unix/gtmcrypt_dbk_ref.h b/sr_unix/gtmcrypt_dbk_ref.h
index 7cb6d07..be69dc5 100644
--- a/sr_unix/gtmcrypt_dbk_ref.h
+++ b/sr_unix/gtmcrypt_dbk_ref.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,65 +12,240 @@
#ifndef GTMCRYPT_DBK_REF_H
#define GTMCRYPT_DBK_REF_H
-#define DATABASE_LINE_INFO 0
-#define SYMMETRIC_KEY_LINE_INFO 1
-#define DATABASE_LINE_INDICATOR "dat "
-#define SYMMETRIC_KEY_LINE_INDICATOR "key "
-#define DATABASE_LINE_INDICATOR_SIZE (SIZEOF(DATABASE_LINE_INDICATOR) - 1)
-#define SYMMETRIC_KEY_LINE_INDICATOR_SIZE (SIZEOF(SYMMETRIC_KEY_LINE_INDICATOR) - 1)
-#define INVALID_FILE_FORMAT 0x0
-#define LIBCONFIG_FILE_FORMAT 0x1
-#define DBKEYS_FILE_FORMAT 0x2
-#ifdef LINE_MAX
-#undef LINE_MAX
-#endif
-#define LINE_MAX (GTM_PATH_MAX + DATABASE_LINE_INDICATOR_SIZE + 2) /* 2 is just for safety */
+/*
+ * This file defines several structures that store information about every symmetric key that we load as well the encryption /
+ * decryption context for any database or device that uses that particular key. The information about the key includes its raw
+ * content and its hash; those are stored in gtm_keystore_t->typed objects malloced invdividually. To assist lookups based on the
+ * key's hash or name, we have tree structures consisting of gtm_keystore_hash_link_t- and gtm_keystore_keyname_link_t-typed nodes,
+ * respectively. Since we expect hashes to be unique, and the hash information is already stored in gtm_keystore_t nodes, the hash-
+ * based tree's nodes contain no additional information and have a one-to-one and onto relationship with the gtm_keystore_t nodes.
+ * The keyname-based tree's nodes, on the other hand, also contain the key name information, which may correspond to the database's
+ * name or a user-chosen string, in case of device encryption. Additionally, several databases or devices may use the same key, in
+ * which case one gtm_keystore_t element may be referenced by multiple keyname tree's nodes. An example is given below:
+ *
+ * keystore_by_hash_head keystore_by_keyname_head
+ * (gtm_keystore_hash_link_t *) (gtm_keystore_t *) (gtm_keystore_keyname_link_t *)
+ * | ________ |
+ * ______|_____ | | ______|_____
+ * | link ---|-------------> | key #1 | <-----. .------------|--- link |
+ * | left right | |________| \ / | left right |
+ * |_/_______\__| \/ |_/_______\__|
+ * / \ ________ /\ / \
+ * _______/____ \ | | / \ ______/_____ \
+ * | link ---|-------\-------------> | key #2 | <-----` `-----|--- link | \
+ * | left right | \ |________| | left right | \
+ * |_/_______\__| \ |_/_______\__| \
+ * ... ... \ ________ / ... \
+ * _____\______ | | / _____\______
+ * | link ---|--> | key #3 | <-.------------ / -----------------|--- link |
+ * | left right | |________| \ / | left right |
+ * |_/_______\__| \ ______/_____ |_/_______\__|
+ * ... ... `-|--- link | ... ...
+ * | left right |
+ * |_/_______\__|
+ * ... ...
+ *
+ * Because we resolve database file names' real paths when we read the configuration file, it is possible that one or more databases
+ * might not yet exist (such as when issuing MUPIP CREATE), so we temporarily store whatever information we processed in an
+ * unresolved databases' list, hoping that a later attempt of resolving the path will succeed. The list is singly-linked and consist
+ * of gtm_keystore_keyname_link_t-typed elements; each element contains information about the key name, raw content, and hash.
+ *
+ * As for gtm_keystore_t elements, in addition to the key data they host a pointer to the head of the encryption / decryption state
+ * list as well as to the one element of that list that is specific to database encryption. (Because database encryption does not
+ * preserve its state beyond one block, we only ever create one database encryption and one database decryption state object, which
+ * gets reused continuously.) Unlike devices, which can activate encryption and decryption individually, databases have to have both
+ * encryption and decryption enabled at once. For that reason, if there is a database encryption context entry in one key's contexts
+ * list, there is a database decryption context right after.
+ *
+ * The encryption / decryption contexts list is doubly-linked and consists of gtm_cipher_ctx_t-typed elements. Each element contains
+ * the algorithm-specific (such as OpenSSL or GCRYPT) encryption or decryption state object, initialization vector (used only when
+ * initializing the encryption / decryption state) and a pointer back to its respective key structure. An example is given below:
+ *
+ * ____________________________________________
+ * | cipher_head db_cipher_entry |
+ * .---> | (gtm_cipher_ctx_t *) (gtm_cipher_ctx_t *) |
+ * | |___/__________________________|_____________|
+ * | / |
+ * | / (DB ENCR) ---> (DB DECR)
+ * | ____/____ _________ ____|____ _________
+ * | | prev | <--|- prev | <--|- prev | <--|- prev |
+ * | | next --|--> | next --|--> | next --|--> | next |
+ * | | store | | store | | store | | store |
+ * | |____|____| |____|____| |____|____| |____|____|
+ * | | | | |
+ * `-------'--------------'--------------'--------------`
+ *
+ * For the actual implementation of the above design please refer to gtmcrypt_dbk_ref.c.
+ */
-typedef struct gtm_dbkeys_tbl_struct
+/* Principal structure for storing key information required to perform encryption / decryption. */
+typedef struct gtm_keystore_struct
{
- struct gtm_dbkeys_tbl_struct *next;
- int fileid_dirty;
- int symmetric_key_dirty;
- int index;
- int database_fn_len;
- char database_fn[GTM_PATH_MAX + 1];
- char symmetric_key_fn[GTM_PATH_MAX + 1];
- unsigned char symmetric_key[SYMMETRIC_KEY_MAX + 1];
- unsigned char symmetric_key_hash[GTMCRYPT_HASH_LEN + 1];
- gtm_fileid_ptr_t fileid;
- crypt_key_t encr_key_handle;
- crypt_key_t decr_key_handle;
-} gtm_dbkeys_tbl;
+ unsigned char key[SYMMETRIC_KEY_MAX]; /* Raw symmetric key contents. */
+ unsigned char key_hash[GTMCRYPT_HASH_LEN]; /* SHA-512 hash of symmetric key. */
+ struct gtm_cipher_ctx_struct *cipher_head; /* Linked list of cipher handles for
+ * either encryption or decryption. A list
+ * is needed because multiple devices or
+ * databases can map to the same key, but
+ * the internal encryption / decryption
+ * state cannot be shared. */
+ struct gtm_cipher_ctx_struct *db_cipher_entry; /* Direct pointer to the (only) DB
+ * encryption cipher entry (followed by the
+ * DB decryption entry). */
+} gtm_keystore_t;
-STATICFNDCL gtm_status_t gc_dbk_get_dbkeys_fname(char *fname, int *stat_success);
-STATICFNDCL int gc_dbk_get_single_entry(void *handle, char **db, char **key, int n);
-void gc_dbk_scrub_entries(void);
-void gc_dbk_get_hash(gtm_dbkeys_tbl *entry, gtm_string_t *hash);
-gtm_dbkeys_tbl* gc_dbk_get_entry_by_fileid(gtm_fileid_ptr_t fileid);
-gtm_dbkeys_tbl* gc_dbk_get_entry_by_hash(gtm_string_t *hash);
-gtm_status_t gc_dbk_init_dbkeys_tbl(void);
-gtm_status_t gc_dbk_fill_symkey_hash(gtm_fileid_ptr_t req_fileid, char *req_hash);
+/* Structure for storing the encryption / decryption state for one device or any DB using the key pointed to by the store field. */
+typedef struct gtm_cipher_ctx_struct
+{
+ crypt_key_t handle; /* Encryption / decryption state. */
+ unsigned char iv[GTMCRYPT_IV_LEN]; /* Initialization vector. */
+ gtm_keystore_t *store; /* Pointer to master key object. */
+ struct gtm_cipher_ctx_struct *prev; /* Pointer to previous element. */
+ struct gtm_cipher_ctx_struct *next; /* Pointer to next element. */
+} gtm_cipher_ctx_t;
+
+/* Structure to organize references to the key object by the key name, in a binary search tree fashion. */
+typedef struct gtm_keystore_keyname_link_struct
+{
+ gtm_keystore_t *link; /* Link to respective key object. */
+ char key_name[GTM_PATH_MAX]; /* Logical entity that the symmetric key
+ * maps to. For databases it is the name of
+ * the database file. For devices it is a
+ * user-chosen string. */
+ struct gtm_keystore_keyname_link_struct *left; /* Pointer to left child. */
+ struct gtm_keystore_keyname_link_struct *right; /* Pointer to right child. */
+} gtm_keystore_keyname_link_t;
+
+/* Structure to organize references to the key object by the key hash, in a binary search tree fashion. */
+typedef struct gtm_keystore_hash_link_struct
+{
+ gtm_keystore_t *link; /* Link to respective key object. */
+ struct gtm_keystore_hash_link_struct *left; /* Pointer to left child. */
+ struct gtm_keystore_hash_link_struct *right; /* Pointer to right child. */
+} gtm_keystore_hash_link_t;
+
+/* Structure to temporarily store key information if the real path of the respective database file name could not be obtained. */
+typedef struct gtm_keystore_unres_keyname_link_struct
+{
+ unsigned char key[SYMMETRIC_KEY_MAX]; /* Raw symmetric key contents. */
+ unsigned char key_hash[GTMCRYPT_HASH_LEN]; /* SHA-512 hash of symmetric key. */
+ char key_name[GTM_PATH_MAX]; /* Logical entity that the symmetric key
+ * maps to. For databases it is the name of
+ * the database file. For devices it is a
+ * user-chosen string. */
+ struct gtm_keystore_unres_keyname_link_struct *next; /* Pointer to next element. */
+} gtm_keystore_unres_keyname_link_t;
+
+STATICFNDEF int keystore_refresh(int *new_db_keys, int *new_db_hashes, int *new_dev_keys, int *new_dev_hashes);
+STATICFNDEF int read_files_section(config_t *cfgp, int *n_mappings, int *new_keynames, int *new_hashes);
+STATICFNDEF int read_database_section(config_t *cfgp, int *n_mappings, int *new_keynames, int *new_hashes);
+STATICFNDEF void gtm_keystore_cleanup_node(gtm_keystore_t *);
+void gtm_keystore_cleanup_all(void);
+STATICFNDEF void gtm_keystore_cleanup_hash_tree(gtm_keystore_hash_link_t *entry);
+STATICFNDEF void gtm_keystore_cleanup_keyname_tree(gtm_keystore_keyname_link_t *entry);
+STATICFNDEF void gtm_keystore_cleanup_unres_keyname_list(gtm_keystore_unres_keyname_link_t *entry);
+int gtmcrypt_getkey_by_keyname(char *keyname, int length, gtm_keystore_t **entry,
+ int database, int nulled);
+int gtmcrypt_getkey_by_hash(unsigned char *hash, gtm_keystore_t **entry);
+STATICFNDEF gtm_keystore_t *keystore_lookup_by_hash(unsigned char *hash);
+STATICFNDEF gtm_keystore_t *keystore_lookup_by_keyname(char *keyname, int length, int nulled);
+STATICFNDEF gtm_keystore_t *keystore_lookup_by_unres_keyname(char *keyname, int *error);
+STATICFNDEF gtm_keystore_t *keystore_lookup_by_unres_keyname_hash(unsigned char *hash);
+int keystore_new_cipher_ctx(gtm_keystore_t *entry, char *iv, int length, int action);
+void keystore_remove_cipher_ctx(gtm_cipher_ctx_t *ctx);
-GBLREF int n_dbkeys;
-GBLREF gtm_dbkeys_tbl **fast_lookup_entry;
+/* Allocate a gtm_keystore_t element. */
+#define GC_ALLOCATE_KEYSTORE_ENTRY(X) \
+{ \
+ X = MALLOC(SIZEOF(gtm_keystore_t)); \
+ (X)->cipher_head = NULL; \
+ (X)->db_cipher_entry = NULL; \
+}
+
+/* Allocate a gtm_keystore_xxx_link_t element. */
+#define GC_ALLOCATE_KEYSTORE_LINK(X, TYPE) \
+{ \
+ X = (TYPE *)MALLOC(SIZEOF(TYPE)); \
+ (X)->left = (X)->right = NULL; \
+}
+
+/* Insert a new gtm_keystore_xxx_link_t element in a respective tree. It assumes
+ * (and asserts) that there is no existing matching node.
+ */
+#define INSERT_KEY_LINK(ROOT, LINK, TYPE, FIELD, VALUE, LENGTH, FILL_LEN) \
+{ \
+ int diff; \
+ TYPE *cur_node, **target_node; \
+ \
+ target_node = &ROOT; \
+ while (cur_node = *target_node) /* NOTE: Assignment!!! */ \
+ { \
+ diff = memcmp(cur_node->FIELD, VALUE, LENGTH); \
+ assert(0 != diff); \
+ if (diff < 0) \
+ target_node = &cur_node->left; \
+ else \
+ target_node = &cur_node->right; \
+ } \
+ GC_ALLOCATE_KEYSTORE_LINK(*target_node, TYPE); \
+ (*target_node)->link = LINK; \
+ memset((*target_node)->FIELD, 0, FILL_LEN); \
+ memcpy((*target_node)->FIELD, VALUE, LENGTH); \
+}
+
+/* Find a particular key based on a binary tree with a specific search criterion, such
+ * as the key's name or hash. The macro causes the caller to return the found node.
+ */
+#define LOOKUP_KEY(ROOT, TYPE, FIELD, VALUE, LENGTH, CHECK_NULL) \
+{ \
+ int diff; \
+ TYPE *cur_node; \
+ \
+ cur_node = ROOT; \
+ while (cur_node) \
+ { \
+ diff = memcmp(cur_node->FIELD, VALUE, LENGTH); \
+ if (0 < diff) \
+ cur_node = cur_node->right; \
+ else if ((0 == diff) && \
+ (CHECK_NULL \
+ ? '\0' == *(((char *)cur_node->FIELD) + LENGTH) \
+ : TRUE)) \
+ return cur_node->link; \
+ else \
+ cur_node = cur_node->left; \
+ } \
+ return NULL; \
+}
-#define GC_ALLOCATE_TBL_ENTRY(X) \
-{ \
- X = MALLOC(SIZEOF(gtm_dbkeys_tbl)); \
- (X)->fileid_dirty = TRUE; \
- (X)->symmetric_key_dirty = TRUE; \
- (X)->fileid = NULL; \
- (X)->index = 0; \
+/* Insert a new gtm_keystore_unres_keyname_link_t element in the unresolved keys list. */
+#define INSERT_UNRESOLVED_KEY_LINK(KEY, HASH, KEYNAME) \
+{ \
+ gtm_keystore_unres_keyname_link_t *node; \
+ \
+ node = (gtm_keystore_unres_keyname_link_t *)MALLOC( \
+ SIZEOF(gtm_keystore_unres_keyname_link_t)); \
+ memcpy(node->key, KEY, SYMMETRIC_KEY_MAX); \
+ memcpy(node->key_hash, HASH, GTMCRYPT_HASH_LEN); \
+ memset(node->key_name, 0, GTM_PATH_MAX); \
+ strncpy(node->key_name, KEYNAME, GTM_PATH_MAX); \
+ node->next = keystore_by_unres_keyname_head; \
+ keystore_by_unres_keyname_head = node; \
}
-#define RETURN_IF_INVALID_HANDLE(HANDLE) \
-{ \
- if (0 > (int)HANDLE || ((int)HANDLE > n_dbkeys)) \
- { \
- assert(FALSE); \
- UPDATE_ERROR_STRING("Encryption handle corrupted."); \
- return GC_FAILURE; \
- } \
+/* Remove all elements from the unresolved keys tree. */
+#define REMOVE_UNRESOLVED_KEY_LINKS \
+{ \
+ gtm_keystore_unres_keyname_link_t *curr, *temp; \
+ \
+ curr = keystore_by_unres_keyname_head; \
+ while (curr) \
+ { \
+ temp = curr->next; \
+ FREE(curr); \
+ curr = temp; \
+ } \
+ keystore_by_unres_keyname_head = NULL; \
}
#endif /* GTMCRYPT_DBK_REF_H */
diff --git a/sr_unix/gtmcrypt_entry.c b/sr_unix/gtmcrypt_entry.c
index 9a24894..8934a38 100644
--- a/sr_unix/gtmcrypt_entry.c
+++ b/sr_unix/gtmcrypt_entry.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -50,8 +50,9 @@ gtmcrypt_func_n /* total number of gtmcrypt functions that needs to be dlsym()
#include "gtmcrypt_funclist.h"
#undef GTMCRYPT_DEF
-GBLREF char dl_err[MAX_ERRSTR_LEN];
-GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF char dl_err[MAX_ERRSTR_LEN];
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
error_def(ERR_CRYPTDLNOOPEN);
@@ -136,18 +137,23 @@ uint4 gtmcrypt_entry()
char new_libpath_env[GTM_PATH_MAX], *save_libpath_ptr, save_libpath[GTM_PATH_MAX];
# endif
char libpath[GTM_PATH_MAX], buf[MAX_GTMCRYPT_PLUGIN_STR_LEN], plugin_dir_path[GTM_PATH_MAX];
- char resolved_libpath[GTM_PATH_MAX], resolved_gtmdist[GTM_PATH_MAX];
+ char resolved_libpath[GTM_PATH_MAX], resolved_plugin_dir_path[GTM_PATH_MAX];
mstr trans, env_var = {0, LEN_AND_LIT(GTM_CRYPT_PLUGIN)};
- assert(STRLEN(gtm_dist));
- if (NULL == realpath(gtm_dist, &resolved_gtmdist[0]))
+ if(!gtm_dist_ok_to_use)
+ {
+ SNPRINTF(dl_err, MAX_ERRSTR_LEN, "%%GTM-E-GTMDISTUNVERIF, Environment variable $gtm_dist (%s) "
+ "could not be verified against the executables path", gtm_dist);
+ return ERR_CRYPTDLNOOPEN;
+ }
+ SNPRINTF(plugin_dir_path, GTM_PATH_MAX, "%s/%s", gtm_dist, GTMCRYPT_PLUGIN_DIR_NAME);
+ if (NULL == realpath(plugin_dir_path, resolved_plugin_dir_path))
{
save_errno = errno;
- SNPRINTF(dl_err, MAX_ERRSTR_LEN, "Failed to find symbolic link for %s. %s", gtm_dist, STRERROR(save_errno));
+ SNPRINTF(dl_err, MAX_ERRSTR_LEN, "Failed to find symbolic link for %s. %s", plugin_dir_path, STRERROR(save_errno));
return ERR_CRYPTDLNOOPEN;
}
- SNPRINTF(plugin_dir_path, GTM_PATH_MAX, "%s/%s", resolved_gtmdist, GTMCRYPT_PLUGIN_DIR_NAME);
- plugin_dir_len = STRLEN(plugin_dir_path);
+ plugin_dir_len = STRLEN(resolved_plugin_dir_path);
if ((SS_NORMAL != TRANS_LOG_NAME(&env_var, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long)) || (0 >= trans.len))
{ /* Either $gtm_crypt_plugin is not defined in the environment variable OR it is set to null-string. Fall-back to
* using libgtmcrypt.so
@@ -156,16 +162,17 @@ uint4 gtmcrypt_entry()
} else
libname_ptr = &buf[0]; /* value of $gtm_crypt_plugin */
SNPRINTF(libpath, GTM_PATH_MAX, "%s/%s", plugin_dir_path, libname_ptr);
- if (NULL == realpath(&libpath[0], &resolved_libpath[0]))
+ if (NULL == realpath(libpath, resolved_libpath))
{
save_errno = errno;
SNPRINTF(dl_err, MAX_ERRSTR_LEN, "Failed to find symbolic link for %s. %s", libpath, STRERROR(save_errno));
return ERR_CRYPTDLNOOPEN;
}
/* Symbolic link found. dlopen resolved_libpath */
- if (0 != memcmp(&resolved_libpath[0], plugin_dir_path, plugin_dir_len))
+ if (0 != memcmp(resolved_libpath, resolved_plugin_dir_path, plugin_dir_len))
{ /* resolved_path doesn't contain $gtm_dist/plugin as the prefix */
- SNPRINTF(dl_err, MAX_ERRSTR_LEN, "Symbolic link for %s must be relative to %s", libpath, plugin_dir_path);
+ SNPRINTF(dl_err, MAX_ERRSTR_LEN, "Resolved path for %s must be relative to the resolved path for %s",
+ libpath, plugin_dir_path);
return ERR_CRYPTDLNOOPEN;
}
# ifdef _AIX
diff --git a/sr_unix/gtmcrypt_funclist.h b/sr_unix/gtmcrypt_funclist.h
index c776189..f256cb5 100644
--- a/sr_unix/gtmcrypt_funclist.h
+++ b/sr_unix/gtmcrypt_funclist.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -10,14 +10,15 @@
****************************************************************/
/* Any time a new function gets added to the GT.M encryption interface, add the corresponding entry here. This file is included in
- * `gtmcrypt_entry', by appropriately, defining GTMCRYPT_DEF, to generate necessary string literals and function pointers which
- * is used to `dlsym' symbols from the GT.M encryption shared library.
+ * 'gtmcrypt_entry' by appropriately defining GTMCRYPT_DEF, to generate necessary string literals and function pointers which are
+ * used to 'dlsym' symbols from the GT.M encryption shared library.
*/
-GTMCRYPT_DEF(gtmcrypt_strerror)
GTMCRYPT_DEF(gtmcrypt_init)
-GTMCRYPT_DEF(gtmcrypt_hash_gen)
-GTMCRYPT_DEF(gtmcrypt_encrypt)
-GTMCRYPT_DEF(gtmcrypt_decrypt)
-GTMCRYPT_DEF(gtmcrypt_getkey_by_name)
-GTMCRYPT_DEF(gtmcrypt_getkey_by_hash)
+GTMCRYPT_DEF(gtmcrypt_strerror)
+GTMCRYPT_DEF(gtmcrypt_init_db_cipher_context_by_hash)
+GTMCRYPT_DEF(gtmcrypt_init_device_cipher_context_by_keyname)
+GTMCRYPT_DEF(gtmcrypt_obtain_db_key_hash_by_keyname)
+GTMCRYPT_DEF(gtmcrypt_release_key)
+GTMCRYPT_DEF(gtmcrypt_encrypt_decrypt)
+GTMCRYPT_DEF(gtmcrypt_same_key)
GTMCRYPT_DEF(gtmcrypt_close)
diff --git a/sr_unix/gtmcrypt_interface.h b/sr_unix/gtmcrypt_interface.h
index 2511a46..267d85f 100644
--- a/sr_unix/gtmcrypt_interface.h
+++ b/sr_unix/gtmcrypt_interface.h
@@ -1,35 +1,159 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license If you do not know the terms of *
* the license, please stop and do not read further *
* *
- y***************************************************************/
+ ****************************************************************/
+
+/* WARNING: Include gtm_limits.h prior to including this file. */
#ifndef GTMCRYPT_INTERFACE_H
#define GTMCRYPT_INTERFACE_H
+/* This module defines the interface for a GT.M encryption plug-in implementation. Refer to the function comments for details. */
+
+/* Environment variable containing the obfuscated password for the key ring with which the symmetric keys are encrypted. */
#define GTM_PASSWD_ENV "gtm_passwd"
+/* Length of the plain and in-hex hash string for a symmetric key. We are currently using SHA-512, so the length is 64 bytes. */
#define GTMCRYPT_HASH_LEN 64
#define GTMCRYPT_HASH_HEX_LEN GTMCRYPT_HASH_LEN * 2
+/* Length of the key name (which for databases is an absolute path to the file). */
+#define GTMCRYPT_MAX_KEYNAME_LEN GTM_PATH_MAX
+
+/* Flag to be used whenever password can be obtained interactively. */
#define GTMCRYPT_OP_INTERACTIVE_MODE 0x00000001
-#define GTMCRYPT_INVALID_KEY_HANDLE -1
+/* Special value that indicates invalid / uninitialized encryption state object. */
+#define GTMCRYPT_INVALID_KEY_HANDLE NULL
+
+/* Constants to indicate what IV-handling mode is desired for a particular encryption or decryption operation. */
+#define GTMCRYPT_IV_CONTINUE 0
+#define GTMCRYPT_IV_SET 1
+#define GTMCRYPT_IV_RESET -1
+
+/* Constants to indicate whether a particular operation is of encryption or decryption type. */
+#define GTMCRYPT_OP_ENCRYPT 1
+#define GTMCRYPT_OP_DECRYPT 0
-typedef int gtmcrypt_key_t;
+typedef void * gtmcrypt_key_t;
-_GTM_APIDECL gtm_status_t gtmcrypt_init(int flags);
-_GTM_APIDECL gtm_status_t gtmcrypt_close(void);
-_GTM_APIDECL gtm_status_t gtmcrypt_hash_gen(gtmcrypt_key_t, gtm_string_t *);
-_GTM_APIDECL gtm_status_t gtmcrypt_encrypt(gtmcrypt_key_t, gtm_string_t *, gtm_string_t *);
-_GTM_APIDECL gtm_status_t gtmcrypt_decrypt(gtmcrypt_key_t, gtm_string_t *, gtm_string_t *);
-_GTM_APIDECL gtm_status_t gtmcrypt_getkey_by_hash(gtm_string_t *, gtmcrypt_key_t *);
-_GTM_APIDECL gtm_status_t gtmcrypt_getkey_by_name(gtm_string_t *, gtmcrypt_key_t *);
-_GTM_APIDECL char *gtmcrypt_strerror(void);
+/*
+ * Initialize encryption if not yet initialized. Use this function to load neccessary libraries and set appropriate configuration
+ * options. Upon a successful return this function is never invoked again.
+ *
+ * Arguments: flags Encryption flags to use.
+ *
+ * Returns: 0 if encryption was initialized successfully; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_init(gtm_int_t flags);
+/***********************************************************************************************************************************
+ * Return the error string. Use this function to provide the current error status. The function is normally invoked following a
+ * non-zero return from one of the other functions defined in the interface, which means that each of them should start by clearing
+ * the error buffer.
+ *
+ * Returns: The error string constructed so far.
+ */
+gtm_char_t *gtmcrypt_strerror(void);
+/***********************************************************************************************************************************
+ * Find the key by hash and set up database encryption and decryption state objects, if not created yet. Use this function to locate
+ * a particular key by its hash and, if found, initialize the objects for subsequent encryption and decryption operations on any
+ * database that will use this key, unless already initialized. The reason any database relying on the same key may use the same
+ * encryption and decryption state objects is that for every encryption and decryption operation the initial IV is used, effectively
+ * reverting to the original state.
+ *
+ * Arguments: handle Pointer which should get pointed to the database encryption state object.
+ * hash Hash of the key.
+ * iv Initialization vector to use for encryption or decryption.
+ *
+ * Returns: 0 if the key was found and database encryption and decryption state objects were initialized or existed already; -1
+ * otherwise.
+ */
+gtm_status_t gtmcrypt_init_db_cipher_context_by_hash(gtmcrypt_key_t *handle, gtm_string_t hash, gtm_string_t iv);
+/***********************************************************************************************************************************
+ * Find the key by keyname and set up device encryption or decryption state object. Use this function to locate a particular key by
+ * its name (as specified in the configuration file) and, if found, initialize an object for subsequent encryption or decryption
+ * operations (depending on the 'encrypt' parameter) with one device using this key. Note that, unlike databases, different devices
+ * relying on the same key require individual encryption and decryption state objects as their states evolve with each encryption or
+ * decryption operation.
+ *
+ * Arguments: handle Pointer which should get pointed to the device encryption or decryption state object.
+ * keyname Name of the key.
+ * iv Initialization vector to use for encryption or decryption.
+ * operation Flag indicating whether encryption or decryption is desired; use GTMCRYPT_OP_ENCRYPT or
+ * GTMCRYPT_OP_DECRYPT, respectively.
+ *
+ * Returns: 0 if the key was found and device encryption or decryption state object was initialized; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_init_device_cipher_context_by_keyname(gtmcrypt_key_t *handle, gtm_string_t keyname,
+ gtm_string_t iv, gtm_int_t operation);
+/***********************************************************************************************************************************
+ * Find the key by keyname and obtain its hash. Use this function to locate a particular key by its name and calculate (or copy, if
+ * precalculated) its hash to the 'hash_dest' address. Note that the keyname corresponds to a particular 'files' field in the
+ * configuration file in case of devices, or a path to a database file otherwise.
+ *
+ * Arguments: keyname Name of the key.
+ * hash_dest Pointer to the location where the key's hash is to be copied.
+ *
+ * Returns: 0 if the key was found and key's hash was copied to the specified location; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_obtain_db_key_hash_by_keyname(gtm_string_t keyname, gtm_string_t *hash_dest);
+/***********************************************************************************************************************************
+ * Release the specified encryption or decryption state object, also releasing the decryption state if database encryption state is
+ * specified.
+ *
+ * Arguments: handle Encryption or decryption state object to release.
+ *
+ * Returns: 0 if the operation was successful; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_release_key(gtmcrypt_key_t handle);
+/***********************************************************************************************************************************
+ * Perform encryption or decryption of the provided data based on the specified encryption / decryption state. If the target buffer
+ * pointer is NULL, the operation is done in-place.
+ *
+ * It is also possible to set the initialization vector (IV) to a particular value, or reset it to the original value, before
+ * attempting the operation. The results of mixing different IV modes on the *same* encryption / decryption state object are
+ * different between OpenSSL and Gcrypt, though. The difference is that modifying the IV (iv_mode != GTMCRYPT_IV_CONTINUE) with
+ * OpenSSL does not affect the actual encryption / decryption state, and subsequent IV-non-modifying encryptions / decryptions
+ * (iv_mode == GTMCRYPT_IV_CONTINUE) are performed on whatever state the prior IV-non-modifying encryptions / decryptions arrived
+ * at. With Gcrypt, on the other hand, modifying the IV (iv_mode != GTMCRYPT_IV_CONTINUE) before an operation influences the
+ * subsequent IV-non-modifying (iv_mode == GTMCRYPT_IV_CONTINUE) operations.
+ *
+ * Arguments: handle Encryption state object to use.
+ * unencr_block Block where unencrypted data is read from.
+ * unencr_block_len Length of the unencrypted (and encrypted) data block.
+ * encr_block Block where encrypted data is put into.
+ * operation Flag indicating whether encryption or decryption is desired; use GTMCRYPT_OP_ENCRYPT or
+ * GTMCRYPT_OP_DECRYPT, respectively.
+ * iv_mode Flag indicating whether the initialization vector (IV) should be changed prior to the
+ * operation; use GTMCRYPT_IV_CONTINUE to proceed without changing the IV, GTMCRYPT_IV_SET to
+ * set the IV the value supplied in the iv argument, and GTMCRYPT_IV_RESET to reset the IV to
+ * the value specified at initialization.
+ * iv Initialization vector to set the encryption state to when iv_mode is GTMCRYPT_IV_SET.
+ *
+ * Returns: 0 if the operation succeeded; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_encrypt_decrypt(gtmcrypt_key_t handle, gtm_char_t *src_block, gtm_int_t src_block_len,
+ gtm_char_t *dest_block, gtm_int_t operation, gtm_int_t iv_mode, gtm_string_t iv);
+/***********************************************************************************************************************************
+ * Compare the keys associated with two encryption or decryption state objects.
+ *
+ * Arguments: handle1 First ecryption or decryption state object to use.
+ * handle2 Second ecryption or decryption state object to use.
+ *
+ * Returns: 1 if both encryption or decryption state objects use the same key; 0 otherwise.
+ */
+gtm_int_t gtmcrypt_same_key(gtmcrypt_key_t handle1, gtmcrypt_key_t handle2);
+/***********************************************************************************************************************************
+ * Disable encryption and discard any sensitive data in memory.
+ *
+ * Returns: 0 if the operation succeeded; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_close(void);
#endif
diff --git a/sr_unix/gtmcrypt_pk_ref.c b/sr_unix/gtmcrypt_pk_ref.c
index d906c20..3d08762 100644
--- a/sr_unix/gtmcrypt_pk_ref.c
+++ b/sr_unix/gtmcrypt_pk_ref.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -23,9 +23,9 @@
#include <sys/mman.h>
#include <sys/stat.h> /* BYPASSOK -- see above */
#include <sys/types.h>
-
#include <gpgme.h> /* gpgme functions */
#include <gpg-error.h> /* gcry*_err_t */
+#include <libconfig.h>
#include "gtmxc_types.h" /* xc_string, xc_status_t and other callin interfaces xc_fileid */
@@ -53,9 +53,7 @@ void gc_pk_scrub_passwd()
* is obtained from the ENVIRONMENT VARIABLE - $gtm_passwd or by invoking the mumps engine during the "gtmcrypt_init()".
* In either ways, it's guaranteed that when this function is called, the passphrase is already set in the global variable.
*/
-int gc_pk_crypt_passphrase_callback(void *opaque, const char *uid_hint,
- const char *passphrase_info, int last_was_bad,
- int fd)
+int gc_pk_crypt_passphrase_callback(void *opaque, const char *uid_hint, const char *passphrase_info, int last_was_bad, int fd)
{
int write_ret, len;
@@ -118,9 +116,9 @@ gpgme_error_t gc_pk_get_decrypted_key(const char *cipher_file, unsigned char *pl
assert(NULL != pk_crypt_ctx);
assert(0 != STRLEN(cipher_file));
- /* Convert the cipher content in the cipher file into
- * in-memory content. This in-memory content is stored
- * in gpgme_data_t structure. */
+ /* Convert the cipher content in the cipher file into in-memory content.
+ * This in-memory content is stored in gpgme_data_t structure.
+ */
err = gpgme_data_new_from_file(&cipher_data, cipher_file, 1);
if (!err)
{
@@ -138,23 +136,35 @@ gpgme_error_t gc_pk_get_decrypted_key(const char *cipher_file, unsigned char *pl
ecode = gpgme_err_code(err);
if (0 != ecode)
{
- switch(ecode)
+ switch (ecode)
{
case GPG_ERR_BAD_PASSPHRASE:
UPDATE_ERROR_STRING("Incorrect password or error while obtaining password");
break;
case GPG_ERR_ENOENT:
- UPDATE_ERROR_STRING("Encryption key file %s not found", cipher_file);
+ UPDATE_ERROR_STRING("Encryption key file " STR_ARG " not found", ELLIPSIZE(cipher_file));
+ break;
+ case GPG_ERR_EACCES:
+ UPDATE_ERROR_STRING("Encryption key file " STR_ARG " not accessible", ELLIPSIZE(cipher_file));
+ break;
+ case GPG_ERR_ENAMETOOLONG:
+ UPDATE_ERROR_STRING("Path, or a component of the path, to encryption key file " STR_ARG
+ " is too long", ELLIPSIZE(cipher_file));
break;
default:
- UPDATE_ERROR_STRING("%s", gpgme_strerror(err));
+ UPDATE_ERROR_STRING("Error while accessing key file " STR_ARG ": %s", ELLIPSIZE(cipher_file),
+ gpgme_strerror(err));
break;
}
+ } else
+ {
+ assert((0 == plain_text_length) || (NULL != plain_data));
}
if (NULL != plain_data)
- { /* scrub plaintext data before releasing it */
+ { /* Scrub plaintext data before releasing it */
assert(SYMMETRIC_KEY_MAX == SIZEOF(null_buffer));
memset(null_buffer, 0, SYMMETRIC_KEY_MAX);
+ assert((0 != ecode) || (0 != plain_text_length) || memcmp(plain_text, null_buffer, SYMMETRIC_KEY_MAX));
gpgme_data_write(plain_data, null_buffer, SYMMETRIC_KEY_MAX);
gpgme_data_release(plain_data);
}
@@ -175,16 +185,21 @@ int gc_pk_gpghome_has_permissions()
if (!(ptr = getenv(HOME)))
{
UPDATE_ERROR_STRING(ENV_UNDEF_ERROR, HOME);
- return GC_FAILURE;
+ return -1;
}
SNPRINTF(pathname, GTM_PATH_MAX, "%s/%s", ptr, DOT_GNUPG);
} else
{
+ if (0 == strlen(ptr))
+ {
+ UPDATE_ERROR_STRING(ENV_EMPTY_ERROR, GNUPGHOME);
+ return -1;
+ }
gnupghome_set = TRUE;
strcpy(pathname, ptr);
}
if (-1 != (perms = access(pathname, R_OK | X_OK)))
- return GC_SUCCESS;
+ return 0;
else if (EACCES == errno)
{
if (gnupghome_set)
@@ -192,7 +207,7 @@ int gc_pk_gpghome_has_permissions()
UPDATE_ERROR_STRING("No read permissions on $%s", GNUPGHOME);
} else
UPDATE_ERROR_STRING("No read permissions on $%s/%s", HOME, DOT_GNUPG);
- } else /* some other error */
- UPDATE_ERROR_STRING("Cannot stat on %s - %d", pathname, errno);
- return GC_FAILURE;
+ } else /* Some other error */
+ UPDATE_ERROR_STRING("Cannot stat on " STR_ARG " - %d", ELLIPSIZE(pathname), errno);
+ return -1;
}
diff --git a/sr_unix/gtmcrypt_pk_ref.h b/sr_unix/gtmcrypt_pk_ref.h
index dd3eb11..c2ea6c3 100644
--- a/sr_unix/gtmcrypt_pk_ref.h
+++ b/sr_unix/gtmcrypt_pk_ref.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -52,7 +52,7 @@ int gc_pk_gpghome_has_permissions(void);
{ \
pk_crypt_ctx = NULL; \
UPDATE_ERROR_STRING("Error initializing GpgME: %s/%s", gpgme_strsource(err), gpgme_strerror(err)); \
- return GC_FAILURE; \
+ return -1; \
} \
}
diff --git a/sr_unix/gtmcrypt_ref.c b/sr_unix/gtmcrypt_ref.c
index d94ab1a..4dc4358 100644
--- a/sr_unix/gtmcrypt_ref.c
+++ b/sr_unix/gtmcrypt_ref.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -25,6 +25,7 @@
#include <gpg-error.h> /* gcry*_err_t */
#include <openssl/err.h>
+#include <libconfig.h>
#include "gtmxc_types.h" /* gtm_string, gtm_status_t and other callin interfaces gtm_fileid */
@@ -40,203 +41,359 @@
#define GTMSHR_IMAGENAME "libgtmshr.dll"
#endif
-#define MESSAGE1 "Verify encrypted key file and your GNUPGHOME settings"
-#define MESSAGE2_DBKEYS "Verify encryption key in configuration file pointed to by $gtm_dbkeys"
-#define MESSAGE2_LIBCONFIG "Verify encryption key in configuration file pointed to by $gtmcrypt_config"
+#define CHECK_IV_LENGTH(IV) \
+{ \
+ if (IV.length > GTMCRYPT_IV_LEN) \
+ { \
+ UPDATE_ERROR_STRING("Specified IVEC has length %ld, which is greater than " \
+ "the maximum allowed IVEC length %d", iv.length, GTMCRYPT_IV_LEN); \
+ return -1; \
+ } \
+}
-GBLDEF int gtmcrypt_inited;
-GBLDEF int gtmcrypt_init_flags;
+GBLDEF int gtmcrypt_inited;
+GBLDEF int gtmcrypt_init_flags;
-GBLREF int gc_dbk_file_format;
-GBLREF passwd_entry_t *gtmcrypt_pwent;
+GBLREF passwd_entry_t *gtmcrypt_pwent;
-_GTM_APIDEF char* gtmcrypt_strerror()
+/*
+ * Return the error string.
+ *
+ * Returns: The error string constructed so far.
+ */
+char* gtmcrypt_strerror()
{
return gtmcrypt_err_string;
}
-_GTM_APIDEF gtm_status_t gtmcrypt_init(int flags)
+/*
+ * Initialize encryption if not yet initialized.
+ *
+ * Arguments: flags Encryption flags to use.
+ *
+ * Returns: 0 if encryption was initialized successfully; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_init(gtm_int_t flags)
{
- int fips_requested, fips_enabled, rv;
+ int fips_requested, fips_enabled, rv;
if (gtmcrypt_inited)
- return GC_SUCCESS;
+ return 0;
if (0 != gc_load_gtmshr_symbols())
- return GC_FAILURE;
-# ifndef USE_OPENSSL
+ return -1;
+# ifdef USE_GCRYPT
gcry_set_log_handler(gtm_gcry_log_handler, NULL);
# endif
IS_FIPS_MODE_REQUESTED(fips_requested);
if (fips_requested)
{
-# ifndef USE_OPENSSL
+# ifdef USE_GCRYPT
# ifndef GCRYPT_NO_FIPS
if (0 != (rv = gcry_control(GCRYCTL_FORCE_FIPS_MODE)))
{
GC_APPEND_GCRY_ERROR(rv, "Failed to initialize FIPS mode.");
- return GC_FAILURE;
+ return -1;
}
# endif
# else
ENABLE_FIPS_MODE(rv, fips_enabled);
+ /* Relevant error detail populated in the above macro. */
if (-1 == rv)
- return GC_FAILURE; /* Relevant error detail populated in the above macro. */
+ return -1;
# endif
}
-# ifndef USE_OPENSSL
+# ifdef USE_GCRYPT
if (0 != gc_sym_init())
- return GC_FAILURE;
+ return -1;
# endif
GC_PK_INIT;
/* Update $gtm_passwd for future invocation */
if (0 != gc_update_passwd(GTM_PASSWD_ENV, >mcrypt_pwent, GTMCRYPT_DEFAULT_PASSWD_PROMPT,
GTMCRYPT_OP_INTERACTIVE_MODE & flags))
{
- return GC_FAILURE;
+ return -1;
}
gtmcrypt_inited = TRUE;
gtmcrypt_init_flags = flags;
- return GC_SUCCESS;
+ gtmcrypt_err_string[0] = '\0';
+ return 0;
}
-_GTM_APIDEF gtm_status_t gtmcrypt_getkey_by_name(gtm_string_t *filename, gtmcrypt_key_t *handle)
+/*
+ * Find the key by hash and set up database encryption and decryption state objects, if not created yet.
+ *
+ * Arguments: handle Pointer which should get pointed to the database encryption state object.
+ * hash Hash of the key.
+ * iv Initialization vector to use for encryption or decryption.
+ *
+ * Returns: 0 if the key was found and database encryption and decryption state objects were initialized or existed already; -1
+ * otherwise.
+ */
+gtm_status_t gtmcrypt_init_db_cipher_context_by_hash(gtmcrypt_key_t *handle, gtm_string_t hash, gtm_string_t iv)
{
- gtm_fileid_ptr_t fileid = NULL;
- gtm_dbkeys_tbl *entry;
- gtm_status_t status = 0;
+ gtm_keystore_t *entry;
+ gtm_cipher_ctx_t **ctx;
GC_VERIFY_INITED;
- *handle = GTMCRYPT_INVALID_KEY_HANDLE;
- gtmcrypt_err_string[0] = '\0'; /* discard any previously recorded error messages */
- if (!GTM_FILENAME_TO_ID(filename, &fileid))
+ /* Discard any previously recorded error messages. */
+ gtmcrypt_err_string[0] = '\0';
+ CHECK_IV_LENGTH(iv);
+ if (hash.length != GTMCRYPT_HASH_LEN)
{
- UPDATE_ERROR_STRING("Database file %s not found", filename->address);
- return GC_FAILURE;
- }
- if (NULL == (entry = gc_dbk_get_entry_by_fileid(fileid)))
- { /* Try re-loading the configuration/db-keys file before giving up. */
- if (0 != gc_dbk_init_dbkeys_tbl())
- return GC_FAILURE; /* No point continuing. */
- status = gc_dbk_fill_symkey_hash(fileid, NULL);
+ UPDATE_ERROR_STRING("Specified symmetric key hash has length %ld, which is different from "
+ "the expected hash length %d", hash.length, GTMCRYPT_HASH_LEN);
+ return -1;
}
- if (0 == status)
+ ctx = (gtm_cipher_ctx_t **)handle;
+ if (0 != gtmcrypt_getkey_by_hash((unsigned char *)hash.address, &entry))
+ return -1;
+ assert(NULL != entry);
+ if (NULL == entry->db_cipher_entry)
{
- entry = gc_dbk_get_entry_by_fileid(fileid);
- if (NULL == entry)
- {
- UPDATE_ERROR_STRING("Database file %s missing in DB keys file or does not exist", filename->address);
- return GC_FAILURE;
- }
- *handle = entry->index;
+ /* This cipher context is for decryption; iv is a static global. */
+ if (0 != keystore_new_cipher_ctx(entry, iv.address, iv.length, GTMCRYPT_OP_DECRYPT))
+ return -1;
+ /* And this cipher context (inserted ahead of the first one) is for encryption. */
+ if (0 != keystore_new_cipher_ctx(entry, iv.address, iv.length, GTMCRYPT_OP_ENCRYPT))
+ return -1;
+ entry->db_cipher_entry = entry->cipher_head;
}
- return status;
+ *ctx = entry->db_cipher_entry;
+ assert(NULL != (*ctx)->next);
+ return 0;
}
-_GTM_APIDEF gtm_status_t gtmcrypt_getkey_by_hash(gtm_string_t *hash, gtmcrypt_key_t *handle)
+/*
+ * Find the key by keyname and set up device encryption or decryption state object.
+ *
+ * Arguments: handle Pointer which should get pointed to the device encryption or decryption state object.
+ * keyname Name of the key.
+ * iv Initialization vector to use for encryption or decryption.
+ * operation Flag indicating whether encryption or decryption is desired; use GTMCRYPT_OP_ENCRYPT or
+ * GTMCRYPT_OP_DECRYPT, respectively.
+ *
+ * Returns: 0 if the key was found and device encryption or decryption state object was initialized; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_init_device_cipher_context_by_keyname(gtmcrypt_key_t *handle, gtm_string_t keyname,
+ gtm_string_t iv, gtm_int_t operation)
{
- gtm_dbkeys_tbl *entry;
- gtm_status_t status = 0;
- int err_caused_by_gpg;
- char save_err[MAX_GTMCRYPT_ERR_STRLEN], hex_buff[GTMCRYPT_HASH_HEX_LEN + 1];
- char *alert_msg;
+ gtm_keystore_t *entry;
+ gtm_cipher_ctx_t **ctx;
- *handle = GTMCRYPT_INVALID_KEY_HANDLE;
GC_VERIFY_INITED;
- gtmcrypt_err_string[0] = '\0'; /* discard any previously recorded error messages */
- if (NULL == (entry = gc_dbk_get_entry_by_hash(hash)))
- { /* Try re-loading the configuration/db-keys file before giving up. */
- if (0 != gc_dbk_init_dbkeys_tbl())
- return GC_FAILURE; /* No point continuing. */
- status = gc_dbk_fill_symkey_hash(NULL, hash->address);
- }
- if (0 == status)
- {
- entry = gc_dbk_get_entry_by_hash(hash);
- if (NULL == entry)
- { /* Lookup still failed. Verify if we have right permissions on GNUPGHOME or $HOME/.gnupg
- * (if GNUPGHOME is unset). If not, then the below function will store the appropriate
- * error message in err_string and so return GC_FAILURE.
- */
- if (GC_SUCCESS != gc_pk_gpghome_has_permissions())
- return GC_FAILURE;
- err_caused_by_gpg = ('\0' != gtmcrypt_err_string[0]);
- if (err_caused_by_gpg)
- alert_msg = MESSAGE1;
- else
- {
- assert((DBKEYS_FILE_FORMAT == gc_dbk_file_format) || (LIBCONFIG_FILE_FORMAT == gc_dbk_file_format));
- alert_msg = (DBKEYS_FILE_FORMAT == gc_dbk_file_format ? MESSAGE2_DBKEYS : MESSAGE2_LIBCONFIG);
- }
- GC_HEX(hash->address, hex_buff, GTMCRYPT_HASH_HEX_LEN);
- if (err_caused_by_gpg)
- {
- strcpy(save_err, gtmcrypt_err_string);
- UPDATE_ERROR_STRING("Expected hash - %s - %s. %s", hex_buff, save_err, alert_msg);
- } else
- UPDATE_ERROR_STRING("Expected hash - %s. %s", hex_buff, alert_msg);
- return GC_FAILURE;
- }
- *handle = entry->index;
- }
- return status;
+ /* Discard any previously recorded error messages. */
+ gtmcrypt_err_string[0] = '\0';
+ CHECK_IV_LENGTH(iv);
+ ctx = (gtm_cipher_ctx_t **)handle;
+ if (0 != gtmcrypt_getkey_by_keyname(keyname.address, keyname.length, &entry, FALSE, FALSE))
+ return -1;
+ assert(NULL != entry);
+ if (0 != keystore_new_cipher_ctx(entry, iv.address, iv.length, operation))
+ return -1;
+ *ctx = entry->cipher_head;
+ return 0;
}
-_GTM_APIDEF gtm_status_t gtmcrypt_hash_gen(gtmcrypt_key_t handle, gtm_string_t *hash)
+/*
+ * Find the key by keyname and obtain its hash.
+ *
+ * Arguments: keyname Name of the key.
+ * hash_dest Pointer to the location where the key's hash is to be copied.
+ *
+ * Returns: 0 if the key was found and key's hash was copied to the specified location; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_obtain_db_key_hash_by_keyname(gtm_string_t keyname, gtm_string_t *hash_dest)
{
- gtm_dbkeys_tbl *entry;
+ gtm_keystore_t *entry;
+ char real_filename[GTM_PATH_MAX];
+ int length;
GC_VERIFY_INITED;
- RETURN_IF_INVALID_HANDLE(handle);
- gtmcrypt_err_string[0] = '\0'; /* discard any previously recorded error messages */
- entry = (gtm_dbkeys_tbl *)fast_lookup_entry[(int)handle];
- gc_dbk_get_hash(entry, hash);
- return GC_SUCCESS;
+ /* Discard any previously recorded error messages. */
+ gtmcrypt_err_string[0] = '\0';
+ /* Since this is a database-specific operation, the keyname parameter happens to be the database's path, which needs to be
+ * fully resolved before we can reliably use it, hence realpath-ing.
+ */
+ if (NULL == realpath(keyname.address, real_filename))
+ {
+ UPDATE_ERROR_STRING("Could not obtain the real path of the database " STR_ARG, ELLIPSIZE(keyname.address));
+ return -1;
+ }
+ length = strlen(real_filename);
+ if (0 != gtmcrypt_getkey_by_keyname(real_filename, length + 1, &entry, TRUE, TRUE))
+ return -1;
+ assert(NULL != entry);
+ hash_dest->length = GTMCRYPT_HASH_LEN;
+ hash_dest->address = (char *)entry->key_hash;
+ return 0;
}
-_GTM_APIDEF gtm_status_t gtmcrypt_encrypt(gtmcrypt_key_t handle, gtm_string_t *unencrypted_block, gtm_string_t *encrypted_block)
+/*
+ * Release the specified encryption or decryption state object, also releasing the decryption state if database encryption state is
+ * specified.
+ *
+ * Arguments: handle Encryption or decryption state object to release.
+ *
+ * Returns: 0 if the operation was successful; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_release_key(gtmcrypt_key_t handle)
{
- gtm_dbkeys_tbl *entry;
- crypt_key_t key;
+ gtm_cipher_ctx_t *ctx;
GC_VERIFY_INITED;
- RETURN_IF_INVALID_HANDLE(handle);
- gtmcrypt_err_string[0] = '\0'; /* discard any previously recorded error messages */
- entry = (gtm_dbkeys_tbl *)fast_lookup_entry[(int)handle];
- /* NOTE: The below assignment, while seemingly innocuous, is important. `entry->encr_key_handle' is a scalar type in
- * OpenSSL (EVP_CIPHER_CTX). The below assignments does a "deep copy" of `entry->encr_key_handle' into `key'. This way,
- * we *always* use a fresh copy of the key before encrypting. By doing so, we implicitly reset the encryption state
- * engine.
+ assert(GTMCRYPT_INVALID_KEY_HANDLE != handle);
+ /* Discard any previously recorded error messages. */
+ gtmcrypt_err_string[0] = '\0';
+ ctx = (gtm_cipher_ctx_t *)handle;
+ /* In case a database encryption state object is specified, we want to make sure that the respective database decryption
+ * state object is also removed.
*/
- key = entry->encr_key_handle;
- GC_SYM_ENCRYPT(&key, unencrypted_block, encrypted_block);
- return GC_SUCCESS;
+ if (ctx->store->db_cipher_entry == ctx)
+ {
+ assert(NULL != ctx->next);
+ keystore_remove_cipher_ctx(ctx->next);
+ }
+ keystore_remove_cipher_ctx(ctx);
+ return 0;
}
-_GTM_APIDEF gtm_status_t gtmcrypt_decrypt(gtmcrypt_key_t handle, gtm_string_t *encrypted_block, gtm_string_t *unencrypted_block)
+/*
+ * Perform encryption or decryption of the provided data based on the specified encryption / decryption state. If the target buffer
+ * pointer is NULL, the operation is done in-place.
+ *
+ * It is also possible to set the initialization vector (IV) to a particular value, or reset it to the original value, before
+ * attempting the operation. The results of mixing different IV modes on the *same* encryption / decryption state object are
+ * different between OpenSSL and Gcrypt, though. The difference is that modifying the IV (iv_mode != GTMCRYPT_IV_CONTINUE) with
+ * OpenSSL does not affect the actual encryption / decryption state, and subsequent IV-non-modifying encryptions / decryptions
+ * (iv_mode == GTMCRYPT_IV_CONTINUE) are performed on whatever state the prior IV-non-modifying encryptions / decryptions arrived
+ * at. With Gcrypt, on the other hand, modifying the IV (iv_mode != GTMCRYPT_IV_CONTINUE) before an operation influences the
+ * subsequent IV-non-modifying (iv_mode == GTMCRYPT_IV_CONTINUE) operations.
+ *
+ * Arguments: handle Encryption state object to use.
+ * unencr_block Block where unencrypted data is read from.
+ * unencr_block_len Length of the unencrypted (and encrypted) data block.
+ * encr_block Block where encrypted data is put into.
+ * operation Flag indicating whether encryption or decryption is desired; use GTMCRYPT_OP_ENCRYPT or
+ * GTMCRYPT_OP_DECRYPT, respectively.
+ * iv_mode Flag indicating whether the initialization vector (IV) should be changed prior to the
+ * operation; use GTMCRYPT_IV_CONTINUE to proceed without changing the IV, GTMCRYPT_IV_SET to
+ * set the IV the value supplied in the iv argument, and GTMCRYPT_IV_RESET to reset the IV to
+ * the value specified at initialization.
+ * iv Initialization vector to set the encryption state to when iv_mode is GTMCRYPT_IV_SET.
+ *
+ * Returns: 0 if the operation succeeded; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_encrypt_decrypt(gtmcrypt_key_t handle, gtm_char_t *src_block, gtm_int_t src_block_len,
+ gtm_char_t *dest_block, gtm_int_t operation, gtm_int_t iv_mode, gtm_string_t iv)
{
- gtm_dbkeys_tbl *entry;
+ gtm_cipher_ctx_t *ctx;
+ crypt_key_t *key_ptr;
+# ifdef USE_OPENSSL
crypt_key_t key;
+# endif
+ char iv_array[GTMCRYPT_IV_LEN];
GC_VERIFY_INITED;
- RETURN_IF_INVALID_HANDLE(handle);
- gtmcrypt_err_string[0] = '\0'; /* discard any previously recorded error messages */
- entry = (gtm_dbkeys_tbl *)fast_lookup_entry[(int)handle];
- /* NOTE: The below assignment, while seemingly innocuous, is important. `entry->decr_key_handle' is a scalar type in
- * OpenSSL (EVP_CIPHER_CTX). The below assignments does a "deep copy" of `entry->decr_key_handle' into `key'. This way,
- * we *always* use a fresh copy of the key before decrypting. By doing so, we implicitly reset the encryption state
- * engine.
- */
- key = entry->decr_key_handle;
- GC_SYM_DECRYPT(&key, encrypted_block, unencrypted_block);
- return GC_SUCCESS;
+ assert(GTMCRYPT_INVALID_KEY_HANDLE != handle);
+ /* Discard any previously recorded error messages. */
+ gtmcrypt_err_string[0] = '\0';
+ ctx = (gtm_cipher_ctx_t *)handle;
+ assert(NULL != ctx);
+ if (GTMCRYPT_IV_SET == iv_mode)
+ {
+ CHECK_IV_LENGTH(iv);
+ memset(iv_array, 0, GTMCRYPT_IV_LEN);
+ memcpy(iv_array, iv.address, iv.length);
+ if (GTMCRYPT_OP_DECRYPT == operation)
+ { /* We expect the IV to be set on a particular operation only for databases, which is why we obtain the
+ * correct crypt_key_t object in case of decryption.
+ */
+ ctx = ctx->next;
+ assert(NULL != ctx);
+ }
+# ifdef USE_OPENSSL
+ /* NOTE: The below assignment, while seemingly innocuous, is important because the encryption / decryption state
+ * object is of a scalar type in OpenSSL (EVP_CIPHER_CTX), and so we only affect its copy when updating the IV and
+ * performing the encryption / decryption operation.
+ */
+ key = ctx->handle;
+ key_ptr = &key;
+ if (!EVP_CipherInit(key_ptr, ALGO, ctx->store->key, (unsigned char *)iv.address, operation))
+ {
+ GC_APPEND_OPENSSL_ERROR("Failed to initialize encryption key handle.");
+ return -1;
+ }
+# endif
+# ifdef USE_GCRYPT
+ gcry_cipher_setiv(ctx->handle, iv.address, GTMCRYPT_IV_LEN);
+ key_ptr = &ctx->handle;
+# endif
+ } else if (GTMCRYPT_IV_RESET == iv_mode)
+ {
+ if (GTMCRYPT_OP_DECRYPT == operation)
+ { /* We expect the IV to be reset on a particular operation only for databases, which is why we obtain the
+ * correct crypt_key_t object in case of decryption.
+ */
+ ctx = ctx->next;
+ assert(NULL != ctx);
+ }
+# ifdef USE_OPENSSL
+ /* NOTE: The below assignment, while seemingly innocuous, is important because the encryption / decryption state
+ * object is of a scalar type in OpenSSL (EVP_CIPHER_CTX), and so we only affect its copy when performing the
+ * encryption / decryption operation.
+ */
+ key = ctx->handle;
+ key_ptr = &key;
+# endif
+# ifdef USE_GCRYPT
+ gcry_cipher_setiv(ctx->handle, ctx->iv, GTMCRYPT_IV_LEN);
+ key_ptr = &ctx->handle;
+# endif
+ } else
+ { /* For devices, encryption and decryption state should be maintained right from the first byte, and for this purpose
+ * the IV should not be reset as that causes a fresh state initialization.
+ */
+ key_ptr = &ctx->handle;
+ }
+ if (0 != gc_sym_encrypt_decrypt(key_ptr, (unsigned char *)src_block, src_block_len, (unsigned char *)dest_block, operation))
+ return -1;
+ return 0;
+}
+
+/*
+ * Compare the keys associated with two encryption or decryption state objects.
+ *
+ * Arguments: handle1 First ecryption or decryption state object to use.
+ * handle2 Second ecryption or decryption state object to use.
+ *
+ * Returns: 1 if both encryption or decryption state objects use the same key; 0 otherwise.
+ */
+gtm_int_t gtmcrypt_same_key(gtmcrypt_key_t handle1, gtmcrypt_key_t handle2)
+{
+ gtm_cipher_ctx_t *ctx1, *ctx2;
+
+ assert((GTMCRYPT_INVALID_KEY_HANDLE != handle1) && (GTMCRYPT_INVALID_KEY_HANDLE != handle2));
+ ctx1 = (gtm_cipher_ctx_t *)handle1;
+ ctx2 = (gtm_cipher_ctx_t *)handle2;
+ if (ctx1 == NULL)
+ return (ctx2 == NULL);
+ if (ctx2 == NULL)
+ return 0;
+ return (ctx1->store == ctx2->store);
}
-_GTM_APIDEF gtm_status_t gtmcrypt_close()
+/*
+ * Disable encryption and discard any sensitive data in memory.
+ *
+ * Returns: 0 if the operation succeeded; -1 otherwise.
+ */
+gtm_status_t gtmcrypt_close()
{
GC_VERIFY_INITED;
- gtmcrypt_err_string[0] = '\0'; /* discard any previously recorded error messages */
+ /* Discard any previously recorded error messages. */
+ gtmcrypt_err_string[0] = '\0';
gc_pk_scrub_passwd();
- gc_dbk_scrub_entries();
+ gtm_keystore_cleanup_all();
gtmcrypt_inited = FALSE;
- return GC_SUCCESS;
+ return 0;
}
diff --git a/sr_unix/gtmcrypt_ref.h b/sr_unix/gtmcrypt_ref.h
index 9993c1f..c612c45 100644
--- a/sr_unix/gtmcrypt_ref.h
+++ b/sr_unix/gtmcrypt_ref.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,30 +22,23 @@ typedef EVP_CIPHER_CTX crypt_key_t;
typedef gcry_cipher_hd_t crypt_key_t;
#endif
-#define GC_ENCRYPT 1
-#define GC_DECRYPT 0
-#define GC_FAILURE 1
-#define GC_SUCCESS 0
-#define DOT_GTM_DBKEYS ".gtm_dbkeys"
#define DOT_GNUPG ".gnupg"
#define SYMMETRIC_KEY_MAX 32
+#define GTMCRYPT_IV_LEN 16
#define GC_MIN_STATIC_BLOCK_SIZE 4096 /* Have a good size block, so that we dont keep reallocating */
/* Some environment variables that encryption plugin cares about */
#define GNUPGHOME "GNUPGHOME"
-#define GTM_DBKEYS "gtm_dbkeys"
#define HOME "HOME"
-/* Following makes sure that at no point we are in the encryption library without gtmcrypt_init getting called
- * prior to the current call
- */
+/* Following makes sure that at no point we are in the encryption library without a prior call to gtmcrypt_init. */
#define GC_VERIFY_INITED \
{ \
if (!gtmcrypt_inited) \
{ \
UPDATE_ERROR_STRING("Encryption library has not been initialized"); \
- return GC_FAILURE; \
+ return -1; \
} \
}
diff --git a/sr_unix/gtmcrypt_sym_ref.c b/sr_unix/gtmcrypt_sym_ref.c
index 8331ca2..48d9d0d 100644
--- a/sr_unix/gtmcrypt_sym_ref.c
+++ b/sr_unix/gtmcrypt_sym_ref.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,6 +18,10 @@
#include <assert.h>
#include <errno.h>
+#include <gpgme.h> /* gpgme functions */
+#include <gpg-error.h> /* gcry*_err_t */
+#include <libconfig.h>
+
#include "gtmxc_types.h"
#include "gtmcrypt_util.h"
@@ -26,13 +30,18 @@
#include "gtmcrypt_ref.h"
#include "gtmcrypt_dbk_ref.h"
#include "gtmcrypt_sym_ref.h"
+#include "gtmcrypt_pk_ref.h"
#ifndef USE_OPENSSL
+/*
+ * Initialize encryption state if libgcrypt is used.
+ *
+ * Returns: 0 if the initialization succeeded; -1 otherwise.
+ */
int gc_sym_init()
{
- gcry_error_t rv;
+ gcry_error_t rv;
- memset(iv, 0, IV_LEN);
if (!gcry_check_version(GCRYPT_VERSION))
{
UPDATE_ERROR_STRING("libgcrypt version mismatch. %s or higher is required", GCRYPT_VERSION);
@@ -52,87 +61,104 @@ int gc_sym_init()
}
#endif
-int gc_sym_create_key_handles(gtm_dbkeys_tbl *entry)
+/*
+ * Destroy the specified encryption / decryption state object.
+ *
+ * Arguments: handle Encryption / decryption state object to destroy.
+ */
+void gc_sym_destroy_cipher_handle(crypt_key_t handle)
+{
+# ifdef USE_OPENSSL
+ EVP_CIPHER_CTX_cleanup(&handle);
+# endif
+# ifdef USE_GCRYPT
+ if (handle)
+ gcry_cipher_close(handle);
+# endif
+}
+
+/*
+ * Create an encryption / decryption state object based on the specified key and IV and assign it to the passed pointer.
+ *
+ * Arguments: raw_key Raw contents of the symmetric key to use.
+ * iv Initialization vector to use.
+ * handle Pointer to assign the newly created encryption / decryption state object to.
+ * direction Indicator of whether encryption or decryption state object is to be constructed.
+ *
+ * Returns: 0 if the state object was successfully constructed; -1 otherwise.
+ */
+int gc_sym_create_cipher_handle(unsigned char *raw_key, unsigned char *iv, crypt_key_t *handle, int direction)
{
- int rv;
- unsigned char *key;
+ int rv, plain_text_length;
- key = entry->symmetric_key;
# ifdef USE_OPENSSL
- /* Create the encryption key handle. */
- EVP_CIPHER_CTX_init(&entry->encr_key_handle);
- if (!EVP_CipherInit(&entry->encr_key_handle, ALGO, key, NULL, GC_ENCRYPT))
+ EVP_CIPHER_CTX_init(handle);
+ if (!EVP_CipherInit(handle, ALGO, raw_key, iv, direction))
{
GC_APPEND_OPENSSL_ERROR("Failed to initialize encryption key handle.");
return -1;
}
- /* Create the decryption key handle. */
- EVP_CIPHER_CTX_init(&entry->decr_key_handle);
- if (0 == (rv = EVP_CipherInit(&entry->decr_key_handle, ALGO, key, NULL, GC_DECRYPT)))
- {
- GC_APPEND_OPENSSL_ERROR("Failed to initialize decryption key handle.");
- return -1;
- }
# else
- if (0 != (rv = gcry_cipher_open(&entry->encr_key_handle, ALGO, MODE, 0)))
+ if (0 != (rv = gcry_cipher_open(handle, ALGO, MODE, 0)))
{
- GC_APPEND_GCRY_ERROR(rv, "Failed to initialize encryption key handle (`gcry_cipher_open').");
+ GC_APPEND_GCRY_ERROR(rv, "Failed to initialize encryption key handle ('gcry_cipher_open').");
return -1;
}
- if (0 != (rv = gcry_cipher_setkey(entry->encr_key_handle, key, SYMMETRIC_KEY_MAX)))
+ if (0 != (rv = gcry_cipher_setkey(*handle, raw_key, SYMMETRIC_KEY_MAX)))
{
- GC_APPEND_GCRY_ERROR(rv, "Failed to initialize encryption key handle (`gcry_cipher_setkey').");
- return -1;
- }
- if (0 != (rv = gcry_cipher_open(&entry->decr_key_handle, ALGO, MODE, 0)))
- {
- GC_APPEND_GCRY_ERROR(rv, "Failed to initialize decryption key handle (`gcry_cipher_open').");
- return -1;
- }
- if (0 != (rv = gcry_cipher_setkey(entry->decr_key_handle, key, SYMMETRIC_KEY_MAX)))
- {
- GC_APPEND_GCRY_ERROR(rv, "Failed to initialize decryption key handle (`gcry_cipher_setkey').");
+ GC_APPEND_GCRY_ERROR(rv, "Failed to initialize encryption key handle ('gcry_cipher_setkey').");
return -1;
}
+ gcry_cipher_setiv(*handle, iv, GTMCRYPT_IV_LEN);
# endif
return 0;
}
-int gc_sym_encrypt_decrypt(crypt_key_t *key, gtm_string_t *in_block, gtm_string_t *out_block, int flag)
+/*
+ * Perform an encryption or decryption operation using the specified state object and buffers (or buffer, if in-place).
+ *
+ * Arguments: key Pointer to the encryption / decryption state object.
+ * in_block Block from which to take the input data for the operation.
+ * in_block_len Length of the block from which to take the input data for the operation; it should match the length
+ * of the block for the output data, if not NULL.
+ * out_block Block where to place the output data from the operation.
+ * flag Indicator of whether encryption or decryption is to be performed.
+ *
+ * Returns: 0 if the operation went successfully; -1 otherwise.
+ */
+int gc_sym_encrypt_decrypt(crypt_key_t *key, unsigned char *in_block, int in_block_len, unsigned char *out_block, int flag)
{
- int inl, outl, rv, tmp_len;
- unsigned char *in, *out;
+ int rv, tmp_len, out_block_len;
- assert(in_block->address);
- assert(0 < in_block->length);
- in = (unsigned char *)in_block->address;
- out = (NULL == out_block->address) ? in : (unsigned char *)out_block->address;
- outl = inl = in_block->length;
-# ifndef USE_OPENSSL
- if (out == in)
+ assert(in_block);
+ assert(0 < in_block_len);
+ if (NULL == out_block)
+ out_block = in_block;
+ out_block_len = in_block_len;
+# ifdef USE_GCRYPT
+ if (out_block == in_block)
{
- in = NULL;
- inl = 0;
+ in_block = NULL;
+ in_block_len = 0;
}
- /* This is important. We have to reset the IV back to all zeros to reset the encryption state machine. Otherwise, the 'iv'
- * from the previous call to this function would be reused for this call resulting in incorrect encryption/decryption.
- */
- gcry_cipher_setiv(*key, iv, IV_LEN);
- rv = (GC_ENCRYPT == flag) ? gcry_cipher_encrypt(*key, out, outl, in, inl) : gcry_cipher_decrypt(*key, out, outl, in, inl);
+ rv = (GTMCRYPT_OP_ENCRYPT == flag)
+ ? gcry_cipher_encrypt(*key, out_block, out_block_len, in_block, in_block_len)
+ : gcry_cipher_decrypt(*key, out_block, out_block_len, in_block, in_block_len);
if (0 != rv)
{
- GC_APPEND_GCRY_ERROR(rv, "Libgcrypt function `gcry_cipher_encrypt' or `gcry_cipher_decrypt' failed.");
+ GC_APPEND_GCRY_ERROR(rv, "Libgcrypt function 'gcry_cipher_encrypt' or 'gcry_cipher_decrypt' failed.");
return -1;
}
-# else
- if (!EVP_CipherUpdate(key, out, &outl, in, inl))
+# endif
+# ifdef USE_OPENSSL
+ if (!EVP_CipherUpdate(key, out_block, &out_block_len, in_block, in_block_len))
{
- GC_APPEND_OPENSSL_ERROR("OpenSSL function `EVP_CipherUpdate' failed.")
+ GC_APPEND_OPENSSL_ERROR("OpenSSL function 'EVP_CipherUpdate' failed.")
return -1;
}
- if (!EVP_CipherFinal(key, out + outl, &tmp_len))
+ if (!EVP_CipherFinal(key, out_block + out_block_len, &tmp_len))
{
- GC_APPEND_OPENSSL_ERROR("OpenSSL function `EVP_CipherFinal' failed.")
+ GC_APPEND_OPENSSL_ERROR("OpenSSL function 'EVP_CipherFinal' failed.")
return -1;
}
# endif
diff --git a/sr_unix/gtmcrypt_sym_ref.h b/sr_unix/gtmcrypt_sym_ref.h
index 4e620d0..e7693b8 100644
--- a/sr_unix/gtmcrypt_sym_ref.h
+++ b/sr_unix/gtmcrypt_sym_ref.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,7 +24,6 @@
# endif
#elif defined USE_GCRYPT
# if defined(USE_AES256CFB)
-# define IV_LEN 16
# define ALGO GCRY_CIPHER_AES256
# define MODE GCRY_CIPHER_MODE_CFB
# define UNIQ_ENC_PARAM_STRING "AES256CFB"
@@ -33,7 +32,6 @@
# error "Unsupported Algorithm for Libgcrypt"
# endif
STATICDEF int gcry_already_inited;
-STATICDEF char iv[IV_LEN];
#else
# error "Unsupported encryption library. Reference implementation currently supports OpenSSL and Libgcrypt"
#endif /* USE_GCRYPT */
@@ -41,15 +39,11 @@ STATICDEF char iv[IV_LEN];
#define UNIQ_ENC_PARAM_LEN SIZEOF(UNIQ_ENC_PARAM_STRING) - 1
#define HASH_INPUT_BUFF_LEN UNIQ_ENC_PARAM_LEN + SYMMETRIC_KEY_MAX
-#define GC_SYM_DECRYPT(KEY_HANDLE, ENCRYPTED_BLOCK, UNENCRYPTED_BLOCK) \
- gc_sym_encrypt_decrypt(KEY_HANDLE, ENCRYPTED_BLOCK, UNENCRYPTED_BLOCK, GC_DECRYPT)
-
-#define GC_SYM_ENCRYPT(KEY_HANDLE, UNENCRYPTED_BLOCK, ENCRYPTED_BLOCK) \
- gc_sym_encrypt_decrypt(KEY_HANDLE, UNENCRYPTED_BLOCK, ENCRYPTED_BLOCK, GC_ENCRYPT)
-
#ifndef USE_OPENSSL
int gc_sym_init(void);
#endif
-int gc_sym_create_key_handles(gtm_dbkeys_tbl *entry);
-int gc_sym_encrypt_decrypt(crypt_key_t *key, gtm_string_t *in_block, gtm_string_t *out_block, int flag);
+void gc_sym_destroy_key_handles(gtm_keystore_t *entry);
+int gc_sym_create_cipher_handle(unsigned char *raw_key, unsigned char *iv, crypt_key_t *handle, int direction);
+void gc_sym_destroy_cipher_handle(crypt_key_t handle);
+int gc_sym_encrypt_decrypt(crypt_key_t *key, unsigned char *in_block, int in_block_len, unsigned char *out_block, int flag);
#endif /* GTMCRYPT_SYM_REF_H */
diff --git a/sr_unix/gtmcrypt_util.c b/sr_unix/gtmcrypt_util.c
index 3c3f261..560976b 100644
--- a/sr_unix/gtmcrypt_util.c
+++ b/sr_unix/gtmcrypt_util.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,17 +40,14 @@ GBLDEF char gtmcrypt_err_string[MAX_GTMCRYPT_ERR_STRLEN];
#ifndef USE_SYSLIB_FUNCS
GBLDEF gtm_malloc_fnptr_t gtm_malloc_fnptr;
GBLDEF gtm_free_fnptr_t gtm_free_fnptr;
-GBLDEF gtm_filename_to_id_fnptr_t gtm_filename_to_id_fnptr;
-GBLDEF gtm_is_file_identical_fnptr_t gtm_is_file_identical_fnptr;
-GBLDEF gtm_xcfileid_free_fnptr_t gtm_xcfileid_free_fnptr;
#endif
#define SIGPROCMASK(FUNC, NEWSET, OLDSET, RC) \
{ \
- do \
- { \
- RC = sigprocmask(FUNC, NEWSET, OLDSET); \
- } while (-1 == RC && EINTR == errno); \
+ do \
+ { \
+ RC = sigprocmask(FUNC, NEWSET, OLDSET); \
+ } while (-1 == RC && EINTR == errno); \
}
#define Tcsetattr(FDESC, WHEN, TERMPTR, RC, ERRNO) \
@@ -65,7 +62,7 @@ GBLDEF gtm_xcfileid_free_fnptr_t gtm_xcfileid_free_fnptr;
SIGPROCMASK(SIG_BLOCK, &block_ttinout, &oldset, rc); \
do \
{ \
- RC = tcsetattr(FDESC, WHEN, TERMPTR); \
+ RC = tcsetattr(FDESC, WHEN, TERMPTR); \
} while(-1 == RC && EINTR == errno); \
ERRNO = errno; \
SIGPROCMASK(SIG_SETMASK, &oldset, NULL, rc); \
@@ -78,7 +75,7 @@ GBLDEF gtm_xcfileid_free_fnptr_t gtm_xcfileid_free_fnptr;
if (0 >= RC) \
{ \
RC = -1; \
- GC_APPEND_OPENSSL_ERROR("OpenSSL function `EVP_sha512' failed."); \
+ GC_APPEND_OPENSSL_ERROR("OpenSSL function 'EVP_sha512' failed."); \
} else \
RC = 0; \
}
@@ -101,9 +98,6 @@ int gc_load_gtmshr_symbols()
# ifndef USE_SYSLIB_FUNCS
gtm_malloc_fnptr = >m_malloc;
gtm_free_fnptr = >m_free;
- gtm_is_file_identical_fnptr = >m_is_file_identical;
- gtm_filename_to_id_fnptr = >m_filename_to_id;
- gtm_xcfileid_free_fnptr = >m_xcfileid_free;
# endif
return 0;
}
@@ -126,7 +120,7 @@ int gc_read_passwd(char *prompt, char *buf, int maxlen)
char c;
/* Display the prompt */
- printf("\n%s", prompt);
+ printf("%s", prompt);
fflush(stdout); /* BYPASSOK -- cannot use FFLUSH */
/* Determine if the process has a terminal device associated with it */
fd = fileno(stdin);
@@ -211,7 +205,7 @@ int gc_read_passwd(char *prompt, char *buf, int maxlen)
* ------------------
* The input character pointer (in->address) is XOR'ed with the above XOR mask and copied into out->address.
*
- * The `nparm' value is unused when called from C and is there only so that this function can be used as an external call entry-
+ * The 'nparm' value is unused when called from C and is there only so that this function can be used as an external call entry-
* point for M.
*/
int gc_mask_unmask_passwd(int nparm, gtm_string_t *in, gtm_string_t *out)
@@ -308,7 +302,18 @@ int gc_update_passwd(char *name, passwd_entry_t **ppwent, char *prompt, int inte
if ((NULL != pwent) && (0 == strcmp(pwent->env_value, lpasswd)))
return 0; /* No change in the environment value. Nothing more to do. */
len = STRLEN(lpasswd);
- assert((0 == len % 2) && (GTM_PASSPHRASE_MAX * 2 > len));
+ if (0 != len % 2)
+ {
+ UPDATE_ERROR_STRING("Environment variable %s must be a valid hexadecimal string of even length less than %d. "
+ "Length is odd", name, GTM_PASSPHRASE_MAX);
+ return -1;
+ }
+ if (GTM_PASSPHRASE_MAX * 2 <= len)
+ {
+ UPDATE_ERROR_STRING("Environment variable %s must be a valid hexadecimal string of even length less than %d. "
+ "Length is %d", name, GTM_PASSPHRASE_MAX, len);
+ return -1;
+ }
if (NULL != pwent)
gc_freeup_pwent(pwent);
pwent = MALLOC(SIZEOF(passwd_entry_t));
@@ -324,6 +329,12 @@ int gc_update_passwd(char *name, passwd_entry_t **ppwent, char *prompt, int inte
{
/* First, convert from hexadecimal representation to regular representation */
GC_UNHEX(lpasswd, passwd, len);
+ if (len < 0)
+ {
+ UPDATE_ERROR_STRING("Environment variable %s must be a valid hexadecimal string of even length "
+ "less than %d. '%c' is not a valid digit (0-9, a-f, or A-F)", name, GTM_PASSPHRASE_MAX, passwd[0]);
+ return -1;
+ }
/* Now, unobfuscate to get the real password */
passwd_str.address = passwd;
passwd_str.length = len / 2;
diff --git a/sr_unix/gtmcrypt_util.h b/sr_unix/gtmcrypt_util.h
index 628d637..9b32999 100644
--- a/sr_unix/gtmcrypt_util.h
+++ b/sr_unix/gtmcrypt_util.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,37 +16,16 @@
# define assert(x)
#endif
-#include "gtm_sizeof.h" /* for SIZEOF */
+#include "gtm_sizeof.h" /* For SIZEOF. */
+#include "gtm_limits.h" /* For GTM_PATH_MAX. */
#include "gtm_common_defs.h" /* To import common macros implemented by GT.M */
-/* The value 1023 for PATH_MAX is derived using pathconf("path", _PC_PATH_MAX) on z/OS and
- * we figure other POSIX platforms are at least as capable if they don't define PATH_MAX.
- * Since we can't afford to call a function on each use of PATH_MAX/GTM_PATH_MAX, this
- * value is hardcoded here.
- *
- * Note on Linux (at least), PATH_MAX is actually defined in <sys/param.h>. We would include
- * that here unconditionally but on AIX, param.h includes limits.h. Note that regardless of where
- * it gets defined, PATH_MAX needs to be defined prior to including stdlib.h. This is because in a
- * pro build, at least Linux verifies the 2nd parm of realpath() is PATH_MAX bytes or more.
- * Since param.h sets PATH_MAX to 4K on Linux, this can cause structures defined as GTM_PATH_MAX
- * to raise an error when used in the 2nd argument of realpath().
- * Note : The definition of PATH_MAX and GTM_PATH_MAX is borrowed from gtm_limits.h. Change in one
- * should be reflected in the other.
- */
-#ifndef PATH_MAX
-# ifdef __linux__
-# include <sys/param.h>
-# else
-# define PATH_MAX 1023
-# endif
-#endif
-#define GTM_PATH_MAX PATH_MAX + 1
-
#define GTM_DIST_ENV "gtm_dist"
#define USER_ENV "USER"
#define ENV_UNDEF_ERROR "Environment variable %s not set"
#define ENV_EMPTY_ERROR "Environment variable %s set to empty string"
+#define MAX_GTMCRYPT_STR_ARG_LEN 256
#define MAX_GTMCRYPT_ERR_STRLEN 2048
#define GTM_PASSPHRASE_MAX 512
@@ -57,68 +36,106 @@
#define GTMCRYPT_FIPS_ENV "gtmcrypt_FIPS"
-#define GC_H2D(H) ((H >= 'A' && H <= 'F') ? ((H - 'A') + 10) : (H - '0'))
+
+#define GC_H2D(C, RES, MULT) \
+{ \
+ if ((C >= 'A') && (C <= 'F')) \
+ RES = ((C - 'A') + 10) * MULT; \
+ else if ((C >= 'a') && (C <= 'f')) \
+ RES = ((C - 'a') + 10) * MULT; \
+ else if ((C >= '0') && (C <= '9')) \
+ RES = (C - '0') * MULT; \
+ else \
+ RES = -1; \
+}
+
/* Convert SOURCE, sequence of hexadecimal characters, into decimal representation. LEN denotes the length of the SOURCE string.
* NOTE: Hexadecimal characters, presented in SOURCE string, has to be in upper case.
*/
-#define GC_UNHEX(SOURCE, TARGET, LEN) \
-{ \
- int i; \
- for (i = 0; i < LEN; i += 2) \
- TARGET[i/2] = (unsigned char)(GC_H2D(SOURCE[i]) * 16 + GC_H2D(SOURCE[i + 1])); \
+#define GC_UNHEX(SOURCE, TARGET, LEN) \
+{ \
+ int i, res1, res2; \
+ char c; \
+ \
+ for (i = 0; i < LEN; i += 2) \
+ { \
+ c = SOURCE[i]; \
+ GC_H2D(c, res1, 16); \
+ if (res1 < 0) \
+ { \
+ LEN = -1; \
+ TARGET[0] = (char)c; \
+ break; \
+ } \
+ c = SOURCE[i + 1]; \
+ GC_H2D(c, res2, 1); \
+ if (res2 < 0) \
+ { \
+ LEN = -1; \
+ TARGET[0] = (char)c; \
+ break; \
+ } \
+ TARGET[i / 2] = (unsigned char)(res1 + res2); \
+ } \
}
/* Convert SOURCE, sequence of decimal characters, into hexadecimal representation. LEN denotes the length of the SOURCE string. */
-#define GC_HEX(SOURCE, TARGET, LEN) \
-{ \
- int i; \
- for (i = 0; i < LEN; i += 2) \
- SPRINTF(TARGET + i, "%02X", (unsigned char)SOURCE[i / 2]); \
+#define GC_HEX(SOURCE, TARGET, LEN) \
+{ \
+ int i; \
+ \
+ for (i = 0; i < LEN; i += 2) \
+ SPRINTF(TARGET + i, "%02X", (unsigned char)SOURCE[i / 2]); \
}
-#define SNPRINTF(SRC, LEN, ...) \
-{ \
- int rc; \
- \
- do \
- { \
- rc = snprintf(SRC, LEN, __VA_ARGS__); /* BYPASSOK */ \
- } while ((-1 == rc) && (EINTR == errno)); /* EINTR-safe */ \
+#define SNPRINTF(SRC, LEN, ...) \
+{ \
+ int rc; \
+ \
+ do \
+ { \
+ rc = snprintf(SRC, LEN, __VA_ARGS__); /* BYPASSOK */ \
+ } while ((-1 == rc) && (EINTR == errno)); /* EINTR-safe */ \
}
-#define SPRINTF(SRC, ...) \
-{ \
- int rc; \
- \
- do \
- { \
- rc = sprintf(SRC, __VA_ARGS__); /* BYPASSOK */ \
- } while ((-1 == rc) && (EINTR == errno)); /* EINTR-safe */ \
+#define SPRINTF(SRC, ...) \
+{ \
+ int rc; \
+ \
+ do \
+ { \
+ rc = sprintf(SRC, __VA_ARGS__); /* BYPASSOK */ \
+ } while ((-1 == rc) && (EINTR == errno)); /* EINTR-safe */ \
}
/* Some helper error reporting macros. */
-#define UPDATE_ERROR_STRING(...) \
-{ \
- SNPRINTF(gtmcrypt_err_string, MAX_GTMCRYPT_ERR_STRLEN, __VA_ARGS__); \
+#define UPDATE_ERROR_STRING(...) \
+{ \
+ SNPRINTF(gtmcrypt_err_string, MAX_GTMCRYPT_ERR_STRLEN, __VA_ARGS__); \
}
-#define IS_FIPS_MODE_REQUESTED(RV) \
-{ \
- char *ptr; \
- \
- RV = FALSE; \
- if (NULL != (ptr = getenv(GTMCRYPT_FIPS_ENV))) \
- { \
- if ((0 == strcasecmp(ptr, "YES")) \
- || (0 == strcasecmp(ptr, "TRUE")) \
- || (*ptr == '1') \
- || (*ptr == 'Y') \
- || (*ptr == 'y')) \
- { \
- RV = TRUE; \
- } \
- } \
+#define STR_QUOT(X) #X
+#define STR_WRAP(X) STR_QUOT(X)
+#define STR_ARG "%." STR_WRAP(MAX_GTMCRYPT_STR_ARG_LEN) "s%s"
+#define ELLIPSIZE(STR) STR, (strlen(STR) > MAX_GTMCRYPT_STR_ARG_LEN ? "..." : "")
+
+#define IS_FIPS_MODE_REQUESTED(RV) \
+{ \
+ char *ptr; \
+ \
+ RV = FALSE; \
+ if (NULL != (ptr = getenv(GTMCRYPT_FIPS_ENV))) \
+ { \
+ if ((0 == strcasecmp(ptr, "YES")) \
+ || (0 == strcasecmp(ptr, "TRUE")) \
+ || (*ptr == '1') \
+ || (*ptr == 'Y') \
+ || (*ptr == 'y')) \
+ { \
+ RV = TRUE; \
+ } \
+ } \
}
/* In OpenSSL versions prior to 1.0.1, "FIPS_mode_set", the function that enables/disables FIPS mode, is available only
@@ -195,9 +212,6 @@
#ifndef USE_SYSLIB_FUNCS
#define MALLOC (*gtm_malloc_fnptr)
#define FREE (*gtm_free_fnptr)
-#define GTM_FILENAME_TO_ID (*gtm_filename_to_id_fnptr)
-#define GTM_IS_FILE_IDENTICAL (*gtm_is_file_identical_fnptr)
-#define GTM_XCFILEID_FREE (*gtm_xcfileid_free_fnptr)
#else
#define MALLOC malloc
#define FREE free
@@ -211,24 +225,18 @@ typedef struct
int passwd_len; /* Length of the password that's allocated. */
} passwd_entry_t;
-typedef void * (*gtm_malloc_fnptr_t)(size_t);
-typedef void (*gtm_free_fnptr_t)(void *);
-typedef gtm_status_t (*gtm_filename_to_id_fnptr_t)(xc_string_t *, xc_fileid_ptr_t *);
-typedef gtm_status_t (*gtm_is_file_identical_fnptr_t)(xc_fileid_ptr_t, xc_fileid_ptr_t);
-typedef void (*gtm_xcfileid_free_fnptr_t)(xc_fileid_ptr_t);
-
-GBLREF gtm_malloc_fnptr_t gtm_malloc_fnptr;
-GBLREF gtm_free_fnptr_t gtm_free_fnptr;
-GBLREF gtm_filename_to_id_fnptr_t gtm_filename_to_id_fnptr;
-GBLREF gtm_is_file_identical_fnptr_t gtm_is_file_identical_fnptr;
-GBLREF gtm_xcfileid_free_fnptr_t gtm_xcfileid_free_fnptr;
-
-GBLREF char gtmcrypt_err_string[MAX_GTMCRYPT_ERR_STRLEN];
-
-int gc_load_gtmshr_symbols(void);
-void gtm_gcry_log_handler(void *opaque, int level, const char *fmt, va_list arg_ptr);
-int gc_read_passwd(char *prompt, char *buf, int maxlen);
-int gc_mask_unmask_passwd(int nparm, gtm_string_t *in, gtm_string_t *out);
-void gc_freeup_pwent(passwd_entry_t *pwent);
-int gc_update_passwd(char *name, passwd_entry_t **ppwent, char *prompt, int interactive);
+typedef void * (*gtm_malloc_fnptr_t)(size_t);
+typedef void (*gtm_free_fnptr_t)(void *);
+
+GBLREF gtm_malloc_fnptr_t gtm_malloc_fnptr;
+GBLREF gtm_free_fnptr_t gtm_free_fnptr;
+
+GBLREF char gtmcrypt_err_string[MAX_GTMCRYPT_ERR_STRLEN];
+
+int gc_load_gtmshr_symbols(void);
+void gtm_gcry_log_handler(void *opaque, int level, const char *fmt, va_list arg_ptr);
+int gc_read_passwd(char *prompt, char *buf, int maxlen);
+int gc_mask_unmask_passwd(int nparm, gtm_string_t *in, gtm_string_t *out);
+void gc_freeup_pwent(passwd_entry_t *pwent);
+int gc_update_passwd(char *name, passwd_entry_t **ppwent, char *prompt, int interactive);
#endif
diff --git a/sr_unix/gtmhelp.m b/sr_unix/gtmhelp.m
index 1295230..ea0d575 100644
--- a/sr_unix/gtmhelp.m
+++ b/sr_unix/gtmhelp.m
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2002, 2010 Fidelity Information Services, Inc ;
+; Copyright 2002, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -10,101 +10,108 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gtmhelp(subtopic,gbldir)
;
- ;
- new (subtopic,gbldir)
- new $ztrap
- set $ztrap="zgoto "_$zl_":error"
+ new (gbldir,subtopic)
+ zshow "d":zshow ; to capture original $P state - assumes $P is always subscript 1
+ set IO(1)=$io ; to capture the original $IO
+ use $principal:nocenable ; do as soon as there's hope of undoing it, i.e, after 2 prior lines
+ set pio=$zwrite($io) ; in case of an early error
+ new $etrap ; also inportant to get in place
+ set $etrap="zgoto "_$zlevel_":error" ; the code below sets up pio to restore the original $P state
+ set:$io'=IO(1) IO(0)=$io ; now capture $P state - IO(0) means there' a device other than $P
+ if zshow("D",1)["TERMINAL" do
+ . set tmp="$principal:("_$select(zshow("D",1)["NOCENE":"no",1:"")_"cenable"
+ . set tmp=tmp_":ctrap="_$select(zshow("D",1)["CTRA=":$piece($piece(zshow("D",1),"CTRA=",2)," "),1:"""""")
+ . set exception=$zwrite($select(zshow("D",1)["EXCE=""":$piece(zshow("D",1),"EXCE=",2),1:"""""")) ; assumes EXCE last
+ . set tmp=tmp_":exception="_$extract(exception,3,$length(exception)-2)
+ . set pio=tmp_")" ; USE below relies on $ZLEVEL so it's outside this embedded subrout
+ . quit ; the line below enables routine-private CTRAP for CTRL-C;
+ if use $principal:(ctrap=$char(3):exception="zgoto "_$zlevel_":again:$zstatus[""CTRAP"","_$zlevel_":error")
set %gbldir=$zgbldir
set $zgbldir=gbldir
- set dio=$io
- set COUNT=0,NOTFOUND=0
- do parse(subtopic)
- for do display quit:COUNT<0
- if ($zsearch(%gbldir)'="") set $zgbldir=%gbldir
+again set:$data(COUNT) subtopic="" ; <CTRL-C> comes back to here and clears any topic
+ kill (%gbldir,IO,pio,subtopic) ; X-NEW is evil, but performance is not an issue here
+ set COUNT=0,IO="",NOTFOUND=0 ; some initialization
+ do parse(subtopic) ; check for topic passed in
+ for do display quit:COUNT<0 ; drive the real work
+ if ($zsearch(%gbldir)'="") set $zgbldir=%gbldir ; restore caller's global directory
else set $zgbldir=""
- use dio
+ use @pio,IO(1) ; restore $P state and original $IO
quit
;
- ;
-parse(subtopic)
- ;
- ;
+parse(subtopic) ; organize space-delimited input memes into a topic hierarchy
new (subtopic,NEW,COUNT,TOPIC)
set NEW=0
- f i=1:1:$length(subtopic," ") set x=$p(subtopic," ",i) if x'="" do
+ for i=1:1:$length(subtopic," ") set x=$piece(subtopic," ",i) if x'="" do
. set COUNT=COUNT+1,NEW=NEW+1
- . set TOPIC(COUNT)=$$UCASE(x)
+ . set TOPIC(COUNT)=$zconvert(x,"U")
. quit
quit
;
- ;
-display
- ;
- ;
- new (COUNT,TOPIC,MATCH,PROMPT,NEW,NOTFOUND)
- if $g(TOPIC(COUNT))="?" set COUNT=COUNT-1
+display ; do the real work
+ new (COUNT,IO,MATCH,NEW,NOTFOUND,PROMPT,TOPIC)
+ if $get(TOPIC(COUNT))="?" set COUNT=COUNT-1 ; refresh choices on the same topic (leve)
write #
- if $$MATCH do
+ if $$MATCH do ; look up the topic
. if NOTFOUND do
.. write !!,"Sorry, no Documentation on "
.. for i=COUNT+1:1:NEW+COUNT write TOPIC(i)," "
.. set NOTFOUND=0
.. quit
- . for i=1:1:MATCH do print(MATCH(i),i)
- . if $data(@MATCH(MATCH)@("s"))>1&(MATCH=1) do
+ . for set IO=$order(IO(IO),-1) quit:""=IO do ; if juggling devices, send content to both; do $P 2nd
+ .. use IO(IO)
+ .. for i=1:1:MATCH do print(MATCH(i),i) ; drive out lines of text using print
+ .. quit
+ . if $data(@MATCH(MATCH)@("s"))>1&(MATCH=1) do ; if descendent topics show the choices only on $P
.. write $$FORMAT(4)
.. write !!,"Additional information available: ",!!
.. set x=""
.. set subref=$name(@MATCH(MATCH)@("s"))
- .. for set x=$order(@subref@(x)) quit:x="" do
+ .. for set x=$order(@subref@(x)) quit:x="" do ; use a "tabbed" list display
... write $$FORMAT(0)
... write @subref@(x)
... write $$COLUMNS(subref,x)
... do qualifiers($name(@subref@(x)))
... quit
.. quit
- . else for i=1:1:NEW set COUNT=COUNT-1
- . if $zeof write # set COUNT=COUNT-1 quit
+ . else set COUNT=COUNT-NEW ; otherwise, reposition to the start of the current level
+ . if $zeof write # set COUNT=COUNT-1 quit ; No more input, peel back out write # could cause an error
. write $$PROMPT
. read subtopic,!
- . if subtopic="" set COUNT=COUNT-1
- . if subtopic'="" do parse(subtopic)
+ . if subtopic="" set COUNT=COUNT-1 quit:0>COUNT ; no answer means peal back a level
+ . else do parse(subtopic) ; check out the response
. quit
- else do
- . set NOTFOUND=1
- . for i=1:1:COUNT write TOPIC(i)," "
- . for i=1:1:NEW set COUNT=COUNT-1
+ else do ; look up failed
+ . set NOTFOUND=1 ; flag the next call
+ . set COUNT=COUNT-NEW ; reset to the last working level
. quit
quit
;
- ;
-print(ref,i);
- ;
+print(ref,i); ; text output function
new (ref,i,MATCH,COUNT)
write !, at ref
- set y=""
- for set y=$order(@ref@(y)) q:(y="s")!(y="") do
+ set y=""
+ for set y=$order(@ref@(y)) quit:(y="s")!(y="") do
. write $$FORMAT(1)
- . w !, at ref@(y)
- if $data(@ref)>1 do
+ . write !, at ref@(y)
+ . quit
+ if $data(@ref)>1 do
. set subref=$name(@ref@("s")),x=""
- . for set x=$order(@subref@(x)) q:x="" do:($e(^(x))="-")
+ . for set x=$order(@subref@(x)) quit:x="" do:($extract(^(x))="-") ; do lines at this level
.. set MATCH(i)=$name(MATCH(i),COUNT-1*2)
.. write $$FORMAT(1)
.. write !, at subref@(x)
.. set z=""
- .. for set z=$order(@subref@(x,z)) q:z="" do
+ .. for set z=$order(@subref@(x,z)) quit:z="" do ; and its descendents
... write !, at subref@(x,z)
... quit
.. quit
. quit
- quit
- ;
-recursiv(ref,level)
+ quit
;
+recursiv(ref,level) ;
new (COUNT,TOPIC,ref,MATCH,level,PROMPT,FLAG)
set level=level+1
- if ($extract(TOPIC(level))="-")&($get(FLAG)'=1) do
+ if ($extract(TOPIC(level))="-")&($get(FLAG)'=1) do
. set FLAG=1
. for i=COUNT:-1:level set TOPIC(i+1)=TOPIC(i)
. set COUNT=COUNT+1
@@ -113,6 +120,7 @@ recursiv(ref,level)
set ref=$name(@ref@("s",TOPIC(level)))
if TOPIC(level)'="" do:$data(@ref)
. if level=COUNT do
+ .. set PROMPT(level)=TOPIC(level)
.. set MATCH=MATCH+1
.. set MATCH(MATCH)=ref
.. quit
@@ -120,23 +128,22 @@ recursiv(ref,level)
. quit
if TOPIC(level)="*" set TOPIC(level)=""
set x=""
- for set x=$o(@ref) quit:(x="")!("\"_x'[("\"_TOPIC(level))) do
+ for set x=$order(@ref) quit:(x="")!("\"_x'[("\"_TOPIC(level))) do
. set ref=$name(@ref,(level*2)-1)
. set ref=$name(@ref@(x))
+ . set (TOPIC(level),PROMPT(level))=@$name(@ref,level*2)
. if level=COUNT do
- .. for j=1:1:COUNT set PROMPT(j)=@$name(@ref,j*2)
- .. set MATCH=MATCH+1
+ .. set MATCH=MATCH+1
.. set MATCH(MATCH)=ref
.. quit
. if level'=COUNT do recursiv(ref,level)
. quit
quit
-qualifiers(ref) ;
- ;
+qualifiers(ref) ; qualifier lister
new (ref)
if $data(@ref)>1 do
. set ref=$name(@ref@("s")),x="-"
- . for s x=$o(@ref@(x)) quit:x=""!($e(x)'="-") do:($e(^(x))="-")
+ . for set x=$order(@ref@(x)) quit:x=""!($extract(x)'="-") do:($extract(^(x))="-")
.. set count=$get(count)+1
.. if count=1 write !
.. write ^(x)
@@ -145,19 +152,18 @@ qualifiers(ref) ;
. quit
if $get(count)>0 write !!
quit
-error ; Error handler called by $ztrap
;
- set $ztrap=""
- write !,"Error in GT.M help utility"
- set outfile="gtmhelp.dmp"
- open outfile:newversion
- use outfile
- zshow "*"
- close outfile
- use dio
- set $ecode=""
+error ; Error handler called by $etrap
+ set $etrap=""
+ if $zstatus'["IOEOF" do ; EOF is not a "real" error
+ . write !,"Error in GT.M help utility - look at ",$zjobexam("gtmhelpdmp")," for additional information",!
+ . quit
+ if ""'=$get(%gbldir),($zsearch(%gbldir)'="") set $zgbldir=%gbldir ; restore caller's global directory
+ else set $zgbldir=""
+ use @pio,IO(1) ; restore $P state and original $IO
+ set $ecode="" ; caller loses error trace, but generally called by direct mode
quit
-MATCH() ; Return array MATCH which contains all Global references which match
+MATCH() ; return array MATCH containing all global references that match
; the TOPIC array.
new (TOPIC,COUNT,MATCH,PROMPT)
set QUALIFIERS=0
@@ -168,8 +174,9 @@ MATCH() ; Return array MATCH which contains all Global references which match
. set ref="^HELP"
. do recursiv(ref,level)
. quit
- if $g(FLAG)=1 set COUNT=COUNT-1
+ if $get(FLAG)=1 set COUNT=COUNT-1
quit MATCH
+ ;
WIDTH() quit 80 ; Width of the current device
PAGE() quit 24 ; Page length of the current device
FORMAT(newlines)
@@ -180,23 +187,18 @@ FORMAT(newlines)
quit ""
COLUMNS(subref,x)
if $x+12'>$$WIDTH write ?$x\12+1*12
- if $x+$l($o(@subref@(x)))>$$WIDTH w !
+ if $x+$l($order(@subref@(x)))>$$WIDTH write !
if $x+12>$$WIDTH write !
quit ""
PROMPT()
new (COUNT,TOPIC,PROMPT)
write !!
set ref="^HELP"
- for i=1:1:COUNT do
- . set TOPIC(i)=$$UCASE($s($d(PROMPT(i)):PROMPT(i),1:TOPIC(i)))
+ for i=1:1:COUNT do
+ . set TOPIC(i)=$zconvert($select($data(PROMPT(i)):PROMPT(i),1:TOPIC(i)),"U")
. set ref=$name(@ref@("s",TOPIC(i)))
. write @ref," "
. quit
- if COUNT=0 kill PROMPT write "Topic? "
- if COUNT>0 write "Subtopic? "
+ if COUNT=0 kill PROMPT write "Topic? "
+ if COUNT>0 write "Subtopic? "
quit ""
-UCASE(string)
- set lo="abcdefghijklmnopqrstuvwxyz"
- set up="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- quit $translate(string,lo,up)
-
diff --git a/sr_unix/gtminstall.sh b/sr_unix/gtminstall.sh
index 302b71d..b8cdd1d 100644
--- a/sr_unix/gtminstall.sh
+++ b/sr_unix/gtminstall.sh
@@ -1,13 +1,13 @@
#!/bin/sh -
#################################################################
-# #
-# Copyright 2011, 2012 Fidelity Information Services, Inc #
-# #
-# This source code contains the intellectual property #
-# of its copyright holder(s), and is made available #
-# under a license. If you do not know the terms of #
-# the license, please stop and do not read further. #
-# #
+# #
+# Copyright 2014 Fidelity Information Services, Inc #
+# #
+# This source code contains the intellectual property #
+# of its copyright holder(s), and is made available #
+# under a license. If you do not know the terms of #
+# the license, please stop and do not read further. #
+# #
#################################################################
# This script automates the installation of GT.M as much as possible,
@@ -15,11 +15,10 @@
# Current limitation is GNU/Linux on x86 (32- & 64-bit) architectures
# and root installation, but it is intended to relax this in the future.
-# NOTE: This script requires the GNU Wget program to download
+# NOTE: This script requires the GNU wget program to download
# distribution files that are not on the local file system.
-# CAUTION - this script is still experimental and unstable.
-# z/OS, HP-UX on PA-RISC and Tru64 UNIX are not supported.
+# CAUTION - this script is still experimental.
# Revision history
#
@@ -32,6 +31,7 @@
# 2011-03-10 0.10 K.S. Bhaskar - Incorporate review comments to bundle with V5.4-002 distribution
# 2011-05-03 0.11 K.S. Bhaskar - Allow for letter suffix releases
# 2011-10-25 0.12 K.S. Bhaskar - Support option to delete .o files on shared library platforms
+# 2014-08-13 0.13 K.S. Bhaskar - Add verbosity around getting latest version and tarball, if requested
# Turn on debugging if set
if [ "Y" = "$gtm_debug" ] ; then set -x ; fi
@@ -127,11 +127,11 @@ err_exit()
mktmpdir()
{
case `uname -s` in
- AIX | SunOS) tmpdirname="/tmp/${USER}_$$_${timestamp}"
- ( umask 077 ; mkdir $tmpdirname ) ;;
- HP-UX) tmpdirname=`mktemp`
- ( umask 077 ; mkdir $tmpdirname ) ;;
- *) tmpdirname=`mktemp -d` ;;
+ AIX | SunOS) tmpdirname="/tmp/${USER}_$$_${timestamp}"
+ ( umask 077 ; mkdir $tmpdirname ) ;;
+ HP-UX) tmpdirname=`mktemp`
+ ( umask 077 ; mkdir $tmpdirname ) ;;
+ *) tmpdirname=`mktemp -d` ;;
esac
echo $tmpdirname
}
@@ -152,91 +152,91 @@ gtm_group_already="N"
# Process command line
while [ $# -gt 0 ] ; do
case "$1" in
- --build-type*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_buildtype=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_buildtype=$2 ; shift
- else echo "--buildtype needs a value" ; err_exit
- fi
- fi ;;
- --copyenv*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_copyenv=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_copyenv=$2 ; shift
- else echo "--copyenv needs a value" ; err_exit
- fi
- fi
- unset gtm_linkenv
- shift ;;
- --copyexec*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_copyexec=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_copyexec=$2 ; shift
- else echo "--copyexec needs a value" ; err_exit
- fi
- fi
- unset gtm_linkexec
- shift ;;
- --debug) gtm_debug="Y" ; set -x ; shift ;;
- --distrib*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_distrib=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_distrib=$2 ; shift
- else echo "--distrib needs a value" ; err_exit
- fi
- fi
- shift ;;
- --dry-run) gtm_dryrun="Y" ; shift ;;
- --group-restriction) gtm_group_restriction="Y" ; shift ;; # must come before group*
- --group*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_group=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_group=$2 ; shift
- else echo "--group needs a value" ; err_exit
- fi
- fi
- shift ;;
- --help) err_exit ;;
- --installdir*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_installdir=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_installdir=$2 ; shift
- else echo "--installdir needs a value" ; err_exit
- fi
- fi
- shift ;;
- --keep-obj) gtm_keep_obj="Y" ; shift ;;
- --linkenv*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_linkenv=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_linkenv=$2 ; shift
- else echo "--linkenv needs a value" ; err_exit
- fi
- fi
- unset gtm_copyenv
- shift ;;
- --linkexec*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_linkexec=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_linkexec=$2 ; shift
- else echo "--linkexec needs a value" ; err_exit
- fi
- fi
- unset gtm_copyexec
- shift ;;
- --overwrite-existing) gtm_overwrite_existing="Y" ; shift ;;
- --prompt-for-group) gtm_prompt_for_group="Y" ; shift ;;
- --ucaseonly-utils) gtm_lcase_utils="N" ; shift ;;
- --user*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_user=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_user=$2 ; shift
- else echo "--user needs a value" ; err_exit
- fi
- fi
- shift ;;
- --utf8*) tmp=`echo $1 | cut -s -d = -f 2- | tr DEFAULT default`
- if [ -n "$tmp" ] ; then gtm_icu_version=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_icu_version=`echo $2 | tr DEFAULT default`; shift
- else echo "--utf8 needs a value" ; err_exit
- fi
- fi
- shift ;;
- --verbose) gtm_verbose="Y" ; shift ;;
- -*) echo Unrecognized option "$1" ; err_exit ;;
- *) if [ -n "$gtm_version" ] ; then echo Nothing must follow the GT.M version ; err_exit
- else gtm_version=$1 ; shift ; fi
+ --build-type*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_buildtype=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_buildtype=$2 ; shift
+ else echo "--buildtype needs a value" ; err_exit
+ fi
+ fi ;;
+ --copyenv*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_copyenv=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_copyenv=$2 ; shift
+ else echo "--copyenv needs a value" ; err_exit
+ fi
+ fi
+ unset gtm_linkenv
+ shift ;;
+ --copyexec*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_copyexec=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_copyexec=$2 ; shift
+ else echo "--copyexec needs a value" ; err_exit
+ fi
+ fi
+ unset gtm_linkexec
+ shift ;;
+ --debug) gtm_debug="Y" ; set -x ; shift ;;
+ --distrib*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_distrib=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_distrib=$2 ; shift
+ else echo "--distrib needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --dry-run) gtm_dryrun="Y" ; shift ;;
+ --group-restriction) gtm_group_restriction="Y" ; shift ;; # must come before group*
+ --group*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_group=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_group=$2 ; shift
+ else echo "--group needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --help) err_exit ;;
+ --installdir*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_installdir=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_installdir=$2 ; shift
+ else echo "--installdir needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --keep-obj) gtm_keep_obj="Y" ; shift ;;
+ --linkenv*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_linkenv=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_linkenv=$2 ; shift
+ else echo "--linkenv needs a value" ; err_exit
+ fi
+ fi
+ unset gtm_copyenv
+ shift ;;
+ --linkexec*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_linkexec=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_linkexec=$2 ; shift
+ else echo "--linkexec needs a value" ; err_exit
+ fi
+ fi
+ unset gtm_copyexec
+ shift ;;
+ --overwrite-existing) gtm_overwrite_existing="Y" ; shift ;;
+ --prompt-for-group) gtm_prompt_for_group="Y" ; shift ;;
+ --ucaseonly-utils) gtm_lcase_utils="N" ; shift ;;
+ --user*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_user=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_user=$2 ; shift
+ else echo "--user needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --utf8*) tmp=`echo $1 | cut -s -d = -f 2- | tr DEFAULT default`
+ if [ -n "$tmp" ] ; then gtm_icu_version=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_icu_version=`echo $2 | tr DEFAULT default`; shift
+ else echo "--utf8 needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --verbose) gtm_verbose="Y" ; shift ;;
+ -*) echo Unrecognized option "$1" ; err_exit ;;
+ *) if [ -n "$gtm_version" ] ; then echo Nothing must follow the GT.M version ; err_exit
+ else gtm_version=$1 ; shift ; fi
esac
done
if [ "Y" = "$gtm_verbose" ] ; then echo Processed command line ; dump_info ; fi
@@ -255,35 +255,35 @@ esac
gtm_shlib_support="Y"
case ${gtm_hostos}_${gtm_arch} in
aix*) # no Source Forge dirname
- gtm_arch="rs6000" # uname -m is not useful on AIX
- gtm_ftp_dirname="aix"
- gtm_flavor="rs6000"
- gtm_install_flavor="RS6000" ;;
+ gtm_arch="rs6000" # uname -m is not useful on AIX
+ gtm_ftp_dirname="aix"
+ gtm_flavor="rs6000"
+ gtm_install_flavor="RS6000" ;;
hpux_ia64) # no Source Forge dirname
- gtm_ftp_dirname="hpux_ia64"
- gtm_flavor="ia64"
- gtm_install_flavor="IA64" ;;
+ gtm_ftp_dirname="hpux_ia64"
+ gtm_flavor="ia64"
+ gtm_install_flavor="IA64" ;;
linux_i686) gtm_sf_dirname="GT.M-x86-Linux"
- gtm_ftp_dirname="linux"
- gtm_flavor="i686"
- gtm_install_flavor="x86"
- gtm_shlib_support="N" ;;
+ gtm_ftp_dirname="linux"
+ gtm_flavor="i686"
+ gtm_install_flavor="x86"
+ gtm_shlib_support="N" ;;
linux_ia64) # no Source Forge dirname
- gtm_ftp_dirname="linux_ia64"
- gtm_flavor="ia64"
- gtm_install_flavor="IA" ;;
+ gtm_ftp_dirname="linux_ia64"
+ gtm_flavor="ia64"
+ gtm_install_flavor="IA" ;;
linux_s390x) # no Source Forge dirname
- gtm_ftp_dirname="linux_s390x"
- gtm_flavor="s390x"
- gtm_install_flavor="S390X" ;;
+ gtm_ftp_dirname="linux_s390x"
+ gtm_flavor="s390x"
+ gtm_install_flavor="S390X" ;;
linux_x8664) gtm_sf_dirname="GT.M-amd64-Linux"
- gtm_ftp_dirname="linux_x8664"
- gtm_flavor="x8664"
- gtm_install_flavor="x86_64" ;;
+ gtm_ftp_dirname="linux_x8664"
+ gtm_flavor="x8664"
+ gtm_install_flavor="x86_64" ;;
solaris_sparc) # no Source Forge dirname
- gtm_ftp_dirname="sun"
- gtm_flavor="sparc"
- gtm_install_flavor="SPARC" ;;
+ gtm_ftp_dirname="sun"
+ gtm_flavor="sparc"
+ gtm_install_flavor="SPARC" ;;
default) echo Architecture `uname -o` on `uname -m` not supported by this script ; err_exit ;;
esac
@@ -291,16 +291,20 @@ esac
if [ -z "$gtm_version" ] ; then
tmp=`dirname $0`
if [ -e "$tmp/mumps" -a -e "$tmp/_XCMD.m" ] ; then
- gtm_distrib=$tmp
- gtm_dist=$tmp ; export gtm_dist
- chmod +x $gtm_dist/mumps
- tmp=`mktmpdir`
- gtmroutines="$tmp($gtm_dist)" ; export gtmroutines
- gtm_version=`$gtm_dist/mumps -run %XCMD 'write $piece($zversion," ",2)'`
- rm -rf $tmp
+ gtm_distrib=$tmp
+ gtm_dist=$tmp ; export gtm_dist
+ chmod +x $gtm_dist/mumps
+ tmp=`mktmpdir`
+ gtmroutines="$tmp($gtm_dist)" ; export gtmroutines
+ gtm_version=`$gtm_dist/mumps -run %XCMD 'write $piece($zversion," ",2)'`
+ rm -rf $tmp
fi
fi
-if [ "Y" = "$gtm_verbose" ] ; then echo Determined architecture, OS and GT.M version ; dump_info ; fi
+if [ "Y" = "$gtm_verbose" ] ; then
+ echo Determined architecture, OS and GT.M version ; dump_info
+ wget_flags="-P"
+else wget_flags="-qP"
+fi
# See if GT.M version can be determined from meta data
if [ -z "$gtm_distrib" ] ; then
@@ -310,19 +314,30 @@ gtm_tmp=`mktmpdir`
mkdir $gtm_tmp/tmp
if [ -z "$gtm_version" -o "latest" = "`echo "$gtm_version" | tr LATES lates`" ] ; then
case $gtm_distrib in
- http://sourceforge.net/projects/fis-gtm | https://sourceforge.net/projects/fis-gtm)
- if { wget -qP $gtm_tmp ${gtm_distrib}/files/${gtm_sf_dirname}/latest 2>&1 1>${gtm_tmp}/wget_latest.log ; } ; then
- gtm_version=`cat ${gtm_tmp}/latest`
- else echo Unable to determine GT.M version ; err_exit
- fi ;;
- ftp://*)
- if { wget -qP $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/latest 2>&1 1>${gtm_tmp}/wget_latest.log ; } ; then
- gtm_version=`cat ${gtm_tmp}/latest`
- else echo Unable to determine GT.M version ; err_exit
- fi ;;
- *) if [ -f ${gtm_distrib}/latest ] ; then gtm_version=`cat ${gtm_distrib}/latest`
- else echo Unable to determine GT.M version ; err_exit
- fi ;;
+ http://sourceforge.net/projects/fis-gtm | https://sourceforge.net/projects/fis-gtm)
+ if [ "Y" = "$gtm_verbose" ] ; then
+ echo wget ${gtm_distrib}/files/${gtm_sf_dirname}/latest to determine latest version
+ echo Check proxy settings if wget hangs
+ fi
+ if { wget $wget_flags $gtm_tmp ${gtm_distrib}/files/${gtm_sf_dirname}/latest 2>&1 1>${gtm_tmp}/wget_latest.log ; } ; then
+ gtm_version=`cat ${gtm_tmp}/latest`
+ else echo Unable to determine GT.M version ; err_exit
+ fi ;;
+ ftp://*)
+ if [ "Y" = "$gtm_verbose" ] ; then
+ echo wget $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/latest to determine latest version
+ echo Check proxy settings if wget hangs
+ fi
+ if { wget $wget_flags $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/latest 2>&1 1>${gtm_tmp}/wget_latest.log ; } ; then
+ gtm_version=`cat ${gtm_tmp}/latest`
+ else echo Unable to determine GT.M version ; err_exit
+ fi ;;
+ *)
+ if [ -f ${gtm_distrib}/latest ] ; then
+ gtm_version=`cat ${gtm_distrib}/latest`
+ if [ "Y" = "$gtm_verbose" ] ; then echo Version is $gtm_version ; fi
+ else echo Unable to determine GT.M version ; err_exit
+ fi ;;
esac
fi
if [ -z "$gtm_version" ] ; then
@@ -335,19 +350,30 @@ else
tmp=`echo $gtm_version | tr -d .-`
gtm_filename=gtm_${tmp}_${gtm_hostos}_${gtm_flavor}_${gtm_buildtype}.tar.gz
case $gtm_distrib in
- http://sourceforge.net/projects/fis-gtm | https://sourceforge.net/projects/fis-gtm)
- if { ! wget -qP $gtm_tmp ${gtm_distrib}/files/${gtm_sf_dirname}/${gtm_version}/${gtm_filename} \
- 2>&1 1>${gtm_tmp}/wget_dist.log ; } ; then
- echo Unable to download GT.M distribution $gtm_filename ; err_exit
- fi ;;
- ftp://*)
- if { ! wget -qP $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/${tmp}/${gtm_filename} \
- 2>&1 1>${gtm_tmp}/wget_dist.log ; } ; then
- echo Unable to download GT.M distribution $gtm_filename ; err_exit
- fi ;;
- *) if [ -f ${gtm_distrib}/${gtm_filename} ] ; then ln -s ${gtm_distrib}/${gtm_filename} $gtm_tmp
- else echo Unable to locate GT.M distribution file ${gtm_distrib}/${gtm_filename} ; err_exit
- fi ;;
+ http://sourceforge.net/projects/fis-gtm | https://sourceforge.net/projects/fis-gtm)
+ if [ "Y" = "$gtm_verbose" ] ; then
+ echo wget ${gtm_distrib}/files/${gtm_sf_dirname}/${gtm_version}/${gtm_filename} to download tarball
+ echo Check proxy settings if wget hangs
+ fi
+ if { ! wget $wget_flags $gtm_tmp ${gtm_distrib}/files/${gtm_sf_dirname}/${gtm_version}/${gtm_filename} \
+ 2>&1 1>${gtm_tmp}/wget_dist.log ; } ; then
+ echo Unable to download GT.M distribution $gtm_filename ; err_exit
+ fi ;;
+ ftp://*)
+ if [ "Y" = "$gtm_verbose" ] ; then
+ echo wget ${gtm_distrib}/${gtm_ftp_dirname}/${tmp}/${gtm_filename} to download tarball
+ echo Check proxy settings if wget hangs
+ fi
+ if { ! wget $wget_flags $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/${tmp}/${gtm_filename} \
+ 2>&1 1>${gtm_tmp}/wget_dist.log ; } ; then
+ echo Unable to download GT.M distribution $gtm_filename ; err_exit
+ fi ;;
+ *)
+ if [ -f ${gtm_distrib}/${gtm_filename} ] ; then
+ if [ "Y" = "$gtm_verbose" ] ; then echo tarball is ${gtm_distrib}/${gtm_filename} ; fi
+ ln -s ${gtm_distrib}/${gtm_filename} $gtm_tmp
+ else echo Unable to locate GT.M distribution file ${gtm_distrib}/${gtm_filename} ; err_exit
+ fi ;;
esac
( cd $gtm_tmp/tmp ; gzip -d < ${gtm_tmp}/${gtm_filename} | tar xf - 2>&1 1>${gtm_tmp}/tar.log )
fi
@@ -363,7 +389,7 @@ fi
if [ "root" = $tmp ] ; then
if [ -z "$gtm_group" ] ; then gtm_group=`$gtm_id -gn`
else if [ "root" != "$gtm_user" -a "$gtm_group" != "`$gtm_id -Gn $gtm_user | xargs -n 1 | $gtm_grep $gtm_group`" ] ; then
- echo $gtm_user is not a member of $gtm_group ; err_exit
+ echo $gtm_user is not a member of $gtm_group ; err_exit
fi
fi
else
@@ -382,10 +408,10 @@ if [ "Y" = "$gtm_verbose" ] ; then echo Finished checking options and assigning
gtm_configure_in=${gtm_tmp}/configure_${timestamp}.in
if { ! $gtm_id -gn bin 2>/dev/null 1>/dev/null ; } then
if [ "N" = "$gtm_prompt_for_group" -o 54002 -gt `echo $gtm_version | cut -s -d V -f 2- | tr -d A-Za-z.-` ] ; then
- echo y >>$gtm_configure_in
- echo root >>$gtm_configure_in
- echo $gtm_group_restriction >>$gtm_configure_in
- gtm_group_already="Y"
+ echo y >>$gtm_configure_in
+ echo root >>$gtm_configure_in
+ echo $gtm_group_restriction >>$gtm_configure_in
+ gtm_group_already="Y"
fi
fi
echo $gtm_user >>$gtm_configure_in
@@ -402,7 +428,7 @@ if [ -z "$gtm_icu_version" ] ; then echo n >>$gtm_configure_in
else echo y >>$gtm_configure_in
if [ "default" = $gtm_icu_version ] ; then echo n >>$gtm_configure_in
else echo y >>$gtm_configure_in
- echo $gtm_icu_version >>$gtm_configure_in
+ echo $gtm_icu_version >>$gtm_configure_in
fi
fi
echo $gtm_lcase_utils >>$gtm_configure_in
@@ -419,10 +445,8 @@ fi
tmp=`head -1 configure | cut -f 1`
if [ "#!/bin/sh" != "$tmp" ] ; then
echo "#!/bin/sh" >configure.sh
- cat configure >>configure.sh
-else
- cp configure configure.sh
fi
+cat configure >>configure.sh
chmod +x configure.sh
# Stop here if this is a dry run
@@ -437,7 +461,7 @@ if [ -d "$gtm_linkenv" ] ; then
if [ "Y" = "$gtm_verbose" ] ; then echo Linked env ; ls -l $gtm_linkenv ; fi
else if [ -d "$gtm_copyenv" ] ; then
( cd $gtm_linkenv ; cp $gtm_installdir/gtmprofile $gtm_installdir/gtmcshrc ./ )
- if [ "Y" = "$gtm_verbose" ] ; then echo Copied env ; ls -l $gtm_copyenv ; fi
+ if [ "Y" = "$gtm_verbose" ] ; then echo Copied env ; ls -l $gtm_copyenv ; fi
fi
fi
if [ -d "$gtm_linkexec" ] ; then
@@ -445,6 +469,6 @@ if [ -d "$gtm_linkexec" ] ; then
if [ "Y" = "$gtm_verbose" ] ; then echo Linked exec ; ls -l $gtm_linkexec ; fi
else if [ -d "$gtm_copyexec" ] ; then
( cd $gtm_linkexec ; cp $gtm_installdir/gtm ./ )
- if [ "Y" = "$gtm_verbose" ] ; then echo Copied exec ; ls -l $gtm_copyexec ; fi
+ if [ "Y" = "$gtm_verbose" ] ; then echo Copied exec ; ls -l $gtm_copyexec ; fi
fi
fi
diff --git a/sr_unix/gtminstall_Solaris.sh b/sr_unix/gtminstall_Solaris.sh
index fbbde5e..69a5f18 100644
--- a/sr_unix/gtminstall_Solaris.sh
+++ b/sr_unix/gtminstall_Solaris.sh
@@ -1,13 +1,13 @@
#!/usr/xpg4/bin/sh -
#################################################################
-# #
-# Copyright 2011, 2012 Fidelity Information Services, Inc #
-# #
-# This source code contains the intellectual property #
-# of its copyright holder(s), and is made available #
-# under a license. If you do not know the terms of #
-# the license, please stop and do not read further. #
-# #
+# #
+# Copyright 2014 Fidelity Information Services, Inc #
+# #
+# This source code contains the intellectual property #
+# of its copyright holder(s), and is made available #
+# under a license. If you do not know the terms of #
+# the license, please stop and do not read further. #
+# #
#################################################################
# This script automates the installation of GT.M as much as possible,
@@ -15,11 +15,10 @@
# Current limitation is GNU/Linux on x86 (32- & 64-bit) architectures
# and root installation, but it is intended to relax this in the future.
-# NOTE: This script requires the GNU Wget program to download
+# NOTE: This script requires the GNU wget program to download
# distribution files that are not on the local file system.
-# CAUTION - this script is still experimental and unstable.
-# z/OS, HP-UX on PA-RISC and Tru64 UNIX are not supported.
+# CAUTION - this script is still experimental.
# Revision history
#
@@ -32,6 +31,7 @@
# 2011-03-10 0.10 K.S. Bhaskar - Incorporate review comments to bundle with V5.4-002 distribution
# 2011-05-03 0.11 K.S. Bhaskar - Allow for letter suffix releases
# 2011-10-25 0.12 K.S. Bhaskar - Support option to delete .o files on shared library platforms
+# 2014-08-13 0.13 K.S. Bhaskar - Add verbosity around getting latest version and tarball, if requested
# Turn on debugging if set
if [ "Y" = "$gtm_debug" ] ; then set -x ; fi
@@ -127,11 +127,11 @@ err_exit()
mktmpdir()
{
case `uname -s` in
- AIX | SunOS) tmpdirname="/tmp/${USER}_$$_${timestamp}"
- ( umask 077 ; mkdir $tmpdirname ) ;;
- HP-UX) tmpdirname=`mktemp`
- ( umask 077 ; mkdir $tmpdirname ) ;;
- *) tmpdirname=`mktemp -d` ;;
+ AIX | SunOS) tmpdirname="/tmp/${USER}_$$_${timestamp}"
+ ( umask 077 ; mkdir $tmpdirname ) ;;
+ HP-UX) tmpdirname=`mktemp`
+ ( umask 077 ; mkdir $tmpdirname ) ;;
+ *) tmpdirname=`mktemp -d` ;;
esac
echo $tmpdirname
}
@@ -152,91 +152,91 @@ gtm_group_already="N"
# Process command line
while [ $# -gt 0 ] ; do
case "$1" in
- --build-type*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_buildtype=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_buildtype=$2 ; shift
- else echo "--buildtype needs a value" ; err_exit
- fi
- fi ;;
- --copyenv*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_copyenv=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_copyenv=$2 ; shift
- else echo "--copyenv needs a value" ; err_exit
- fi
- fi
- unset gtm_linkenv
- shift ;;
- --copyexec*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_copyexec=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_copyexec=$2 ; shift
- else echo "--copyexec needs a value" ; err_exit
- fi
- fi
- unset gtm_linkexec
- shift ;;
- --debug) gtm_debug="Y" ; set -x ; shift ;;
- --distrib*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_distrib=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_distrib=$2 ; shift
- else echo "--distrib needs a value" ; err_exit
- fi
- fi
- shift ;;
- --dry-run) gtm_dryrun="Y" ; shift ;;
- --group-restriction) gtm_group_restriction="Y" ; shift ;; # must come before group*
- --group*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_group=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_group=$2 ; shift
- else echo "--group needs a value" ; err_exit
- fi
- fi
- shift ;;
- --help) err_exit ;;
- --installdir*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_installdir=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_installdir=$2 ; shift
- else echo "--installdir needs a value" ; err_exit
- fi
- fi
- shift ;;
- --keep-obj) gtm_keep_obj="Y" ; shift ;;
- --linkenv*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_linkenv=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_linkenv=$2 ; shift
- else echo "--linkenv needs a value" ; err_exit
- fi
- fi
- unset gtm_copyenv
- shift ;;
- --linkexec*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_linkexec=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_linkexec=$2 ; shift
- else echo "--linkexec needs a value" ; err_exit
- fi
- fi
- unset gtm_copyexec
- shift ;;
- --overwrite-existing) gtm_overwrite_existing="Y" ; shift ;;
- --prompt-for-group) gtm_prompt_for_group="Y" ; shift ;;
- --ucaseonly-utils) gtm_lcase_utils="N" ; shift ;;
- --user*) tmp=`echo $1 | cut -s -d = -f 2-`
- if [ -n "$tmp" ] ; then gtm_user=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_user=$2 ; shift
- else echo "--user needs a value" ; err_exit
- fi
- fi
- shift ;;
- --utf8*) tmp=`echo $1 | cut -s -d = -f 2- | tr DEFAULT default`
- if [ -n "$tmp" ] ; then gtm_icu_version=$tmp
- else if [ 1 -lt "$#" ] ; then gtm_icu_version=`echo $2 | tr DEFAULT default`; shift
- else echo "--utf8 needs a value" ; err_exit
- fi
- fi
- shift ;;
- --verbose) gtm_verbose="Y" ; shift ;;
- -*) echo Unrecognized option "$1" ; err_exit ;;
- *) if [ -n "$gtm_version" ] ; then echo Nothing must follow the GT.M version ; err_exit
- else gtm_version=$1 ; shift ; fi
+ --build-type*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_buildtype=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_buildtype=$2 ; shift
+ else echo "--buildtype needs a value" ; err_exit
+ fi
+ fi ;;
+ --copyenv*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_copyenv=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_copyenv=$2 ; shift
+ else echo "--copyenv needs a value" ; err_exit
+ fi
+ fi
+ unset gtm_linkenv
+ shift ;;
+ --copyexec*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_copyexec=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_copyexec=$2 ; shift
+ else echo "--copyexec needs a value" ; err_exit
+ fi
+ fi
+ unset gtm_linkexec
+ shift ;;
+ --debug) gtm_debug="Y" ; set -x ; shift ;;
+ --distrib*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_distrib=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_distrib=$2 ; shift
+ else echo "--distrib needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --dry-run) gtm_dryrun="Y" ; shift ;;
+ --group-restriction) gtm_group_restriction="Y" ; shift ;; # must come before group*
+ --group*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_group=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_group=$2 ; shift
+ else echo "--group needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --help) err_exit ;;
+ --installdir*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_installdir=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_installdir=$2 ; shift
+ else echo "--installdir needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --keep-obj) gtm_keep_obj="Y" ; shift ;;
+ --linkenv*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_linkenv=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_linkenv=$2 ; shift
+ else echo "--linkenv needs a value" ; err_exit
+ fi
+ fi
+ unset gtm_copyenv
+ shift ;;
+ --linkexec*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_linkexec=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_linkexec=$2 ; shift
+ else echo "--linkexec needs a value" ; err_exit
+ fi
+ fi
+ unset gtm_copyexec
+ shift ;;
+ --overwrite-existing) gtm_overwrite_existing="Y" ; shift ;;
+ --prompt-for-group) gtm_prompt_for_group="Y" ; shift ;;
+ --ucaseonly-utils) gtm_lcase_utils="N" ; shift ;;
+ --user*) tmp=`echo $1 | cut -s -d = -f 2-`
+ if [ -n "$tmp" ] ; then gtm_user=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_user=$2 ; shift
+ else echo "--user needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --utf8*) tmp=`echo $1 | cut -s -d = -f 2- | tr DEFAULT default`
+ if [ -n "$tmp" ] ; then gtm_icu_version=$tmp
+ else if [ 1 -lt "$#" ] ; then gtm_icu_version=`echo $2 | tr DEFAULT default`; shift
+ else echo "--utf8 needs a value" ; err_exit
+ fi
+ fi
+ shift ;;
+ --verbose) gtm_verbose="Y" ; shift ;;
+ -*) echo Unrecognized option "$1" ; err_exit ;;
+ *) if [ -n "$gtm_version" ] ; then echo Nothing must follow the GT.M version ; err_exit
+ else gtm_version=$1 ; shift ; fi
esac
done
if [ "Y" = "$gtm_verbose" ] ; then echo Processed command line ; dump_info ; fi
@@ -255,35 +255,35 @@ esac
gtm_shlib_support="Y"
case ${gtm_hostos}_${gtm_arch} in
aix*) # no Source Forge dirname
- gtm_arch="rs6000" # uname -m is not useful on AIX
- gtm_ftp_dirname="aix"
- gtm_flavor="rs6000"
- gtm_install_flavor="RS6000" ;;
+ gtm_arch="rs6000" # uname -m is not useful on AIX
+ gtm_ftp_dirname="aix"
+ gtm_flavor="rs6000"
+ gtm_install_flavor="RS6000" ;;
hpux_ia64) # no Source Forge dirname
- gtm_ftp_dirname="hpux_ia64"
- gtm_flavor="ia64"
- gtm_install_flavor="IA64" ;;
+ gtm_ftp_dirname="hpux_ia64"
+ gtm_flavor="ia64"
+ gtm_install_flavor="IA64" ;;
linux_i686) gtm_sf_dirname="GT.M-x86-Linux"
- gtm_ftp_dirname="linux"
- gtm_flavor="i686"
- gtm_install_flavor="x86"
- gtm_shlib_support="N" ;;
+ gtm_ftp_dirname="linux"
+ gtm_flavor="i686"
+ gtm_install_flavor="x86"
+ gtm_shlib_support="N" ;;
linux_ia64) # no Source Forge dirname
- gtm_ftp_dirname="linux_ia64"
- gtm_flavor="ia64"
- gtm_install_flavor="IA" ;;
+ gtm_ftp_dirname="linux_ia64"
+ gtm_flavor="ia64"
+ gtm_install_flavor="IA" ;;
linux_s390x) # no Source Forge dirname
- gtm_ftp_dirname="linux_s390x"
- gtm_flavor="s390x"
- gtm_install_flavor="S390X" ;;
+ gtm_ftp_dirname="linux_s390x"
+ gtm_flavor="s390x"
+ gtm_install_flavor="S390X" ;;
linux_x8664) gtm_sf_dirname="GT.M-amd64-Linux"
- gtm_ftp_dirname="linux_x8664"
- gtm_flavor="x8664"
- gtm_install_flavor="x86_64" ;;
+ gtm_ftp_dirname="linux_x8664"
+ gtm_flavor="x8664"
+ gtm_install_flavor="x86_64" ;;
solaris_sparc) # no Source Forge dirname
- gtm_ftp_dirname="sun"
- gtm_flavor="sparc"
- gtm_install_flavor="SPARC" ;;
+ gtm_ftp_dirname="sun"
+ gtm_flavor="sparc"
+ gtm_install_flavor="SPARC" ;;
default) echo Architecture `uname -o` on `uname -m` not supported by this script ; err_exit ;;
esac
@@ -291,16 +291,20 @@ esac
if [ -z "$gtm_version" ] ; then
tmp=`dirname $0`
if [ -e "$tmp/mumps" -a -e "$tmp/_XCMD.m" ] ; then
- gtm_distrib=$tmp
- gtm_dist=$tmp ; export gtm_dist
- chmod +x $gtm_dist/mumps
- tmp=`mktmpdir`
- gtmroutines="$tmp($gtm_dist)" ; export gtmroutines
- gtm_version=`$gtm_dist/mumps -run %XCMD 'write $piece($zversion," ",2)'`
- rm -rf $tmp
+ gtm_distrib=$tmp
+ gtm_dist=$tmp ; export gtm_dist
+ chmod +x $gtm_dist/mumps
+ tmp=`mktmpdir`
+ gtmroutines="$tmp($gtm_dist)" ; export gtmroutines
+ gtm_version=`$gtm_dist/mumps -run %XCMD 'write $piece($zversion," ",2)'`
+ rm -rf $tmp
fi
fi
-if [ "Y" = "$gtm_verbose" ] ; then echo Determined architecture, OS and GT.M version ; dump_info ; fi
+if [ "Y" = "$gtm_verbose" ] ; then
+ echo Determined architecture, OS and GT.M version ; dump_info
+ wget_flags="-P"
+else wget_flags="-qP"
+fi
# See if GT.M version can be determined from meta data
if [ -z "$gtm_distrib" ] ; then
@@ -310,19 +314,30 @@ gtm_tmp=`mktmpdir`
mkdir $gtm_tmp/tmp
if [ -z "$gtm_version" -o "latest" = "`echo "$gtm_version" | tr LATES lates`" ] ; then
case $gtm_distrib in
- http://sourceforge.net/projects/fis-gtm | https://sourceforge.net/projects/fis-gtm)
- if { wget -qP $gtm_tmp ${gtm_distrib}/files/${gtm_sf_dirname}/latest 2>&1 1>${gtm_tmp}/wget_latest.log ; } ; then
- gtm_version=`cat ${gtm_tmp}/latest`
- else echo Unable to determine GT.M version ; err_exit
- fi ;;
- ftp://*)
- if { wget -qP $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/latest 2>&1 1>${gtm_tmp}/wget_latest.log ; } ; then
- gtm_version=`cat ${gtm_tmp}/latest`
- else echo Unable to determine GT.M version ; err_exit
- fi ;;
- *) if [ -f ${gtm_distrib}/latest ] ; then gtm_version=`cat ${gtm_distrib}/latest`
- else echo Unable to determine GT.M version ; err_exit
- fi ;;
+ http://sourceforge.net/projects/fis-gtm | https://sourceforge.net/projects/fis-gtm)
+ if [ "Y" = "$gtm_verbose" ] ; then
+ echo wget ${gtm_distrib}/files/${gtm_sf_dirname}/latest to determine latest version
+ echo Check proxy settings if wget hangs
+ fi
+ if { wget $wget_flags $gtm_tmp ${gtm_distrib}/files/${gtm_sf_dirname}/latest 2>&1 1>${gtm_tmp}/wget_latest.log ; } ; then
+ gtm_version=`cat ${gtm_tmp}/latest`
+ else echo Unable to determine GT.M version ; err_exit
+ fi ;;
+ ftp://*)
+ if [ "Y" = "$gtm_verbose" ] ; then
+ echo wget $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/latest to determine latest version
+ echo Check proxy settings if wget hangs
+ fi
+ if { wget $wget_flags $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/latest 2>&1 1>${gtm_tmp}/wget_latest.log ; } ; then
+ gtm_version=`cat ${gtm_tmp}/latest`
+ else echo Unable to determine GT.M version ; err_exit
+ fi ;;
+ *)
+ if [ -f ${gtm_distrib}/latest ] ; then
+ gtm_version=`cat ${gtm_distrib}/latest`
+ if [ "Y" = "$gtm_verbose" ] ; then echo Version is $gtm_version ; fi
+ else echo Unable to determine GT.M version ; err_exit
+ fi ;;
esac
fi
if [ -z "$gtm_version" ] ; then
@@ -335,19 +350,30 @@ else
tmp=`echo $gtm_version | tr -d .-`
gtm_filename=gtm_${tmp}_${gtm_hostos}_${gtm_flavor}_${gtm_buildtype}.tar.gz
case $gtm_distrib in
- http://sourceforge.net/projects/fis-gtm | https://sourceforge.net/projects/fis-gtm)
- if { ! wget -qP $gtm_tmp ${gtm_distrib}/files/${gtm_sf_dirname}/${gtm_version}/${gtm_filename} \
- 2>&1 1>${gtm_tmp}/wget_dist.log ; } ; then
- echo Unable to download GT.M distribution $gtm_filename ; err_exit
- fi ;;
- ftp://*)
- if { ! wget -qP $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/${tmp}/${gtm_filename} \
- 2>&1 1>${gtm_tmp}/wget_dist.log ; } ; then
- echo Unable to download GT.M distribution $gtm_filename ; err_exit
- fi ;;
- *) if [ -f ${gtm_distrib}/${gtm_filename} ] ; then ln -s ${gtm_distrib}/${gtm_filename} $gtm_tmp
- else echo Unable to locate GT.M distribution file ${gtm_distrib}/${gtm_filename} ; err_exit
- fi ;;
+ http://sourceforge.net/projects/fis-gtm | https://sourceforge.net/projects/fis-gtm)
+ if [ "Y" = "$gtm_verbose" ] ; then
+ echo wget ${gtm_distrib}/files/${gtm_sf_dirname}/${gtm_version}/${gtm_filename} to download tarball
+ echo Check proxy settings if wget hangs
+ fi
+ if { ! wget $wget_flags $gtm_tmp ${gtm_distrib}/files/${gtm_sf_dirname}/${gtm_version}/${gtm_filename} \
+ 2>&1 1>${gtm_tmp}/wget_dist.log ; } ; then
+ echo Unable to download GT.M distribution $gtm_filename ; err_exit
+ fi ;;
+ ftp://*)
+ if [ "Y" = "$gtm_verbose" ] ; then
+ echo wget ${gtm_distrib}/${gtm_ftp_dirname}/${tmp}/${gtm_filename} to download tarball
+ echo Check proxy settings if wget hangs
+ fi
+ if { ! wget $wget_flags $gtm_tmp ${gtm_distrib}/${gtm_ftp_dirname}/${tmp}/${gtm_filename} \
+ 2>&1 1>${gtm_tmp}/wget_dist.log ; } ; then
+ echo Unable to download GT.M distribution $gtm_filename ; err_exit
+ fi ;;
+ *)
+ if [ -f ${gtm_distrib}/${gtm_filename} ] ; then
+ if [ "Y" = "$gtm_verbose" ] ; then echo tarball is ${gtm_distrib}/${gtm_filename} ; fi
+ ln -s ${gtm_distrib}/${gtm_filename} $gtm_tmp
+ else echo Unable to locate GT.M distribution file ${gtm_distrib}/${gtm_filename} ; err_exit
+ fi ;;
esac
( cd $gtm_tmp/tmp ; gzip -d < ${gtm_tmp}/${gtm_filename} | tar xf - 2>&1 1>${gtm_tmp}/tar.log )
fi
@@ -363,7 +389,7 @@ fi
if [ "root" = $tmp ] ; then
if [ -z "$gtm_group" ] ; then gtm_group=`$gtm_id -gn`
else if [ "root" != "$gtm_user" -a "$gtm_group" != "`$gtm_id -Gn $gtm_user | xargs -n 1 | $gtm_grep $gtm_group`" ] ; then
- echo $gtm_user is not a member of $gtm_group ; err_exit
+ echo $gtm_user is not a member of $gtm_group ; err_exit
fi
fi
else
@@ -382,10 +408,10 @@ if [ "Y" = "$gtm_verbose" ] ; then echo Finished checking options and assigning
gtm_configure_in=${gtm_tmp}/configure_${timestamp}.in
if { ! $gtm_id -gn bin 2>/dev/null 1>/dev/null ; } then
if [ "N" = "$gtm_prompt_for_group" -o 54002 -gt `echo $gtm_version | cut -s -d V -f 2- | tr -d A-Za-z.-` ] ; then
- echo y >>$gtm_configure_in
- echo root >>$gtm_configure_in
- echo $gtm_group_restriction >>$gtm_configure_in
- gtm_group_already="Y"
+ echo y >>$gtm_configure_in
+ echo root >>$gtm_configure_in
+ echo $gtm_group_restriction >>$gtm_configure_in
+ gtm_group_already="Y"
fi
fi
echo $gtm_user >>$gtm_configure_in
@@ -402,7 +428,7 @@ if [ -z "$gtm_icu_version" ] ; then echo n >>$gtm_configure_in
else echo y >>$gtm_configure_in
if [ "default" = $gtm_icu_version ] ; then echo n >>$gtm_configure_in
else echo y >>$gtm_configure_in
- echo $gtm_icu_version >>$gtm_configure_in
+ echo $gtm_icu_version >>$gtm_configure_in
fi
fi
echo $gtm_lcase_utils >>$gtm_configure_in
@@ -419,10 +445,8 @@ fi
tmp=`head -1 configure | cut -f 1`
if [ "#!/bin/sh" != "$tmp" ] ; then
echo "#!/bin/sh" >configure.sh
- cat configure >>configure.sh
-else
- cp configure configure.sh
fi
+cat configure >>configure.sh
chmod +x configure.sh
# Stop here if this is a dry run
@@ -437,7 +461,7 @@ if [ -d "$gtm_linkenv" ] ; then
if [ "Y" = "$gtm_verbose" ] ; then echo Linked env ; ls -l $gtm_linkenv ; fi
else if [ -d "$gtm_copyenv" ] ; then
( cd $gtm_linkenv ; cp $gtm_installdir/gtmprofile $gtm_installdir/gtmcshrc ./ )
- if [ "Y" = "$gtm_verbose" ] ; then echo Copied env ; ls -l $gtm_copyenv ; fi
+ if [ "Y" = "$gtm_verbose" ] ; then echo Copied env ; ls -l $gtm_copyenv ; fi
fi
fi
if [ -d "$gtm_linkexec" ] ; then
@@ -445,6 +469,6 @@ if [ -d "$gtm_linkexec" ] ; then
if [ "Y" = "$gtm_verbose" ] ; then echo Linked exec ; ls -l $gtm_linkexec ; fi
else if [ -d "$gtm_copyexec" ] ; then
( cd $gtm_linkexec ; cp $gtm_installdir/gtm ./ )
- if [ "Y" = "$gtm_verbose" ] ; then echo Copied exec ; ls -l $gtm_copyexec ; fi
+ if [ "Y" = "$gtm_verbose" ] ; then echo Copied exec ; ls -l $gtm_copyexec ; fi
fi
fi
diff --git a/sr_unix/gtmio.h b/sr_unix/gtmio.h
index e1cf0ec..b4dfabc 100644
--- a/sr_unix/gtmio.h
+++ b/sr_unix/gtmio.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -193,93 +193,9 @@ error_def(ERR_PREMATEOF);
#else
#define LOCK_IS_ALLOWED(FDESC, STATUS) STATUS = 0
#endif
-/* The for loop is the workaround for a glitch in read locking in zlink. The primary steps to acquire a
- * read-lock are 1. open the file, and 2. read lock it. If a process creates the initial, empty version
- * of the file (with the OPEN3), but has not yet write-locked it, and meanwhile, another process does its
- * open and gets a read-lock, then a later read within incr_link() will end up reading an empty file. To
- * avoid that problem, readers have to poll for a non-empty object file before reading. If the read lock
- * is obtained, but the file is empty, then release the read lock, sleep for a while, and retry the file open.
- */
-#define OPEN_OBJECT_FILE(FNAME, FFLAG, FDESC) \
-{ \
- int status; \
- struct flock lock; /* arg to lock the file thru fnctl */ \
- int cntr; \
- struct stat stat_buf; \
- pid_t l_pid; \
- ZOS_ONLY(int realfiletag;) \
- \
- l_pid = getpid(); \
- for (cntr = 0; cntr < MAX_FILE_OPEN_TRIES; cntr++) \
- { \
- while (FD_INVALID == (FDESC = OPEN3(FNAME, FFLAG, 0666)) && EINTR == errno) \
- ; \
- if (-1 != FDESC) \
- { \
- LOCK_IS_ALLOWED(FDESC, status); \
- if (-2 != status) \
- { \
- do { \
- lock.l_type = ((O_WRONLY == ((FFLAG) & O_ACCMODE)) || \
- ( O_RDWR == ((FFLAG) & O_ACCMODE))) ? F_WRLCK : F_RDLCK; \
- lock.l_whence = SEEK_SET; /*locking offsets from file beginning*/ \
- lock.l_start = lock.l_len = 0; /* lock the whole file */ \
- lock.l_pid = l_pid; \
- } while (-1 == (status = fcntl(FDESC, F_SETLKW, &lock)) && EINTR == errno); \
- } \
- if (-1 != status) \
- { \
- if ((FFLAG) & O_CREAT) \
- { \
- FTRUNCATE(FDESC, 0, status); \
- ZOS_ONLY( \
- status = gtm_zos_set_tag(FDESC, TAG_BINARY, TAG_NOTTEXT, TAG_FORCE, &realfiletag); \
- ) \
- } else \
- { \
- FSTAT_FILE(FDESC, &stat_buf, status); \
- if (status || (0 == stat_buf.st_size)) \
- { \
- CLOSE_OBJECT_FILE(FDESC, status); \
- SHORT_SLEEP(WAIT_FOR_FILE_TIME); \
- continue; \
- } \
- ZOS_ONLY( \
- status = gtm_zos_tag_to_policy(FDESC, TAG_BINARY, &realfiletag); \
- ) \
- } \
- } \
- if (-1 == status) \
- CLOSEFILE_RESET(FDESC, status);/* can't fail - no writes, no writes-behind */ \
- } \
- break; \
- } \
-}
-#define CONVERT_OBJECT_LOCK(FDESC, FFLAG, RC) \
-{ \
- struct flock lock; /* arg to lock the file thru fnctl */ \
- pid_t l_pid; \
- \
- l_pid = getpid(); \
- do { \
- lock.l_type = FFLAG; \
- lock.l_whence = SEEK_SET; /*locking offsets from file beginning*/ \
- lock.l_start = lock.l_len = 0; /* lock the whole file */ \
- lock.l_pid = l_pid; \
- } while (-1 == (RC = fcntl(FDESC, F_SETLKW, &lock)) && EINTR == errno); \
-}
+#define OPEN_OBJECT_FILE(FNAME, FFLAG, FDESC) FDESC = open_object_file(FNAME, FFLAG);
-#define CLOSE_OBJECT_FILE(FDESC, RC) \
-{ \
- struct flock lock; /* arg to unlock the file thru fnctl */ \
- do { \
- lock.l_type = F_UNLCK; \
- lock.l_whence = SEEK_SET; \
- lock.l_start = lock.l_len = 0; /* unlock the whole file */ \
- lock.l_pid = getpid(); \
- } while (-1 == (RC = fcntl(FDESC, F_SETLK, &lock)) && EINTR == errno); \
- CLOSEFILE_RESET(FDESC, RC); \
-}
+#define CLOSE_OBJECT_FILE(FDESC, RC) CLOSEFILE_RESET(FDESC, RC)
#define CLOSEFILE(FDESC, RC) \
{ \
@@ -738,7 +654,7 @@ error_def(ERR_PREMATEOF);
else if (EINTR != errno) \
break; \
} \
- /* GTMASSERT? */ \
+ /* assertpro(FALSE)? */ \
}
#define DOWRITERC(FDESC, FBUFF, FBUFF_LEN, RC) \
@@ -917,4 +833,10 @@ typedef struct
ENABLE_INTERRUPTS(INTRPT_IN_FFLUSH); \
}
+/* Prototypes */
+int open_object_file(const char *fname, int fflag);
+int mk_tmp_object_file(const char *object_fname, int object_fname_len);
+void rename_tmp_object_file(const char *object_fname);
+void init_object_file_name(void);
+
#endif
diff --git a/sr_unix/gtmlink.c b/sr_unix/gtmlink.c
index 77ac1d8..b426d02 100644
--- a/sr_unix/gtmlink.c
+++ b/sr_unix/gtmlink.c
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2013 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#include "mdef.h"
diff --git a/sr_unix/gtmlink.h b/sr_unix/gtmlink.h
index 42b8569..d130eaf 100644
--- a/sr_unix/gtmlink.h
+++ b/sr_unix/gtmlink.h
@@ -1,13 +1,13 @@
/****************************************************************
-* *
-* Copyright 2013 Fidelity Information Services, Inc *
-* *
-* This source code contains the intellectual property *
-* of its copyright holder(s), and is made available *
-* under a license. If you do not know the terms of *
-* the license, please stop and do not read further. *
-* *
-****************************************************************/
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
#ifndef GTMLINK_H_INCLUDED
#define GTMLINK_H_INCLUDED
diff --git a/sr_unix/gtmprofile.gtc b/sr_unix/gtmprofile.gtc
index 04c9caf..7e12f5e 100644
--- a/sr_unix/gtmprofile.gtc
+++ b/sr_unix/gtmprofile.gtc
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2010, 2013 Fidelity Information Services, Inc.#
+# Copyright 2010, 2014 Fidelity Information Services, Inc.#
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -81,7 +81,7 @@ if [ $gtm_dist != "$old_gtm_dist" ] ; then
which="which"
fi
if [ -z "$gtm_icu_version" -a -n "`$which icu-config`" ] ; then
- gtm_icu_version=`icu-config --version | gtm_chset=M $gtm_dist/mumps -run %XCMD 'Read x Write $Piece(x,".",1,2)'`
+ gtm_icu_version=`icu-config --version | gtm_chset=M $gtm_dist/mumps -run %XCMD 'Read x Write $Select(+x>48:$Piece(x,".",1)/10,1:$Piece(x,".",1,2))'`
export gtm_icu_version
fi
diff --git a/sr_unix/gtmrecv.c b/sr_unix/gtmrecv.c
index 0a78f83..4b5f6ea 100644
--- a/sr_unix/gtmrecv.c
+++ b/sr_unix/gtmrecv.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc *
+ * Copyright 2006, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -69,6 +69,8 @@ GBLREF void (*call_on_signal)();
GBLREF uint4 process_id;
GBLREF recvpool_addrs recvpool;
GBLREF int recvpool_shmid;
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
GBLREF gtmrecv_options_t gtmrecv_options;
GBLREF int gtmrecv_log_fd;
GBLREF FILE *gtmrecv_log_fp;
@@ -79,7 +81,9 @@ GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS];
GBLREF jnlpool_addrs jnlpool;
GBLREF IN_PARMS *cli_lex_in_ptr;
GBLREF uint4 mutex_per_process_init_pid;
+LITREF gtmImageName gtmImageNames[];
+error_def(ERR_GTMDISTUNVERIF);
error_def(ERR_INITORRESUME);
error_def(ERR_MUPCLIERR);
error_def(ERR_NORESYNCSUPPLONLY);
@@ -118,6 +122,9 @@ int gtmrecv(void)
memset((uchar_ptr_t)&recvpool, 0, SIZEOF(recvpool));
if (-1 == gtmrecv_get_opt())
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_MUPCLIERR);
+ if (!gtm_dist_ok_to_use)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, STRLEN(gtm_dist), gtm_dist,
+ gtmImageNames[image_type].imageNameLen, gtmImageNames[image_type].imageName);
if (gtmrecv_options.start || gtmrecv_options.shut_down)
{
jnlpool_init(GTMRECEIVE, (boolean_t)FALSE, (boolean_t *)NULL);
@@ -336,7 +343,7 @@ int gtmrecv(void)
}
}
# ifndef REPL_DEBUG_NOBACKGROUND
- FORK_CLEAN(pid);
+ FORK(pid);
if (0 < pid)
{
REPL_DPRINT2("Waiting for receiver child process %d to startup\n", pid);
@@ -559,10 +566,7 @@ int gtmrecv(void)
if (SS_NORMAL == (status = repl_filter_init(gtmrecv_local->filter_cmd)))
gtmrecv_filter |= EXTERNAL_FILTER;
else
- {
- if (EREPL_FILTERSTART_EXEC == repl_errno)
- gtmrecv_exit(ABNORMAL_SHUTDOWN);
- }
+ gtmrecv_exit(ABNORMAL_SHUTDOWN);
}
gtmrecv_process(!recvpool_ctl->fresh_start);
return (SS_NORMAL);
diff --git a/sr_unix/gtmrecv_fetchresync.c b/sr_unix/gtmrecv_fetchresync.c
index 7e4ebc6..8ace971 100644
--- a/sr_unix/gtmrecv_fetchresync.c
+++ b/sr_unix/gtmrecv_fetchresync.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -454,6 +454,18 @@ int gtmrecv_fetchresync(int port, seq_num *resync_seqno, seq_num max_reg_seqno)
repl_close(>mrecv_sock_fd);
REVERT;
repl_log(stdout, TRUE, TRUE, "Received RESYNC SEQNO is %llu [0x%llx]\n", *resync_seqno, *resync_seqno);
- assert(*resync_seqno <= max_reg_seqno);
+ /* We expect the resync_seqno to be less than or equal to the instance jnl_seqno (which is the maximum reg_seqno
+ * across all regions). The only exception is if this is a supplementary instance and the source side is a
+ * non-supplementary instance in which case the resync_seqno corresponds to a strm_seqno whereas max_reg_seqno
+ * corresponds to the unified jnl_seqno (across all streams) and those are two different dimensions and so cannot
+ * be compared directly. It is possible that the strm_seqno is GREATER than the unified jnl_seqno. Take below example.
+ *
+ * Say in instance A (from A->P terminology) I keep updating the same node ^a=1 a million times.
+ * And do say 100 local updates on P. And then do a mupip load of A's extract onto P and initialize -updateresync
+ * replication between A->P. Then the strm_seqno of strm # 1 would be 1 million + 1 but the jnl_seqno of P would be
+ * only 100 + 1. So the unified jnl_seqno 101 is a lot less than the strm_seqno of 1,000,001. This is a valid scenario
+ * and there is nothing in the code that otherwise requires this ordering for their correct operation.
+ */
+ assert((*resync_seqno <= max_reg_seqno) || jnlpool.repl_inst_filehdr->is_supplementary);
return SS_NORMAL;
}
diff --git a/sr_unix/gtmrecv_process.c b/sr_unix/gtmrecv_process.c
index 1fbb5c4..35c1bdd 100644
--- a/sr_unix/gtmrecv_process.c
+++ b/sr_unix/gtmrecv_process.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc.*
+ * Copyright 2006, 2014 Fidelity Information Services, Inc.*
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -229,7 +229,7 @@ typedef enum
GTM_RECV_CMPBUFF
} gtmrecv_buff_t;
-static unsigned char *buffp, *buff_start, *msgbuff, *filterbuff;
+static unsigned char *buffp, *buff_start, *msgbuff;
static int buff_unprocessed;
static int buffered_data_len;
static int max_recv_bufsiz;
@@ -456,7 +456,7 @@ STATICFNDEF int repl_tr_endian_convert(unsigned char remote_jnl_ver, uchar_ptr_t
break;
}
assert(!IS_ZTP(rectype));
- assert((JRT_HISTREC == rectype) || (JRT_TRIPLE == rectype) || IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype)
+ assert((JRT_HISTREC == rectype) || (JRT_TRIPLE == rectype) || IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype)
|| (JRT_TCOM == rectype) || (JRT_NULL == rectype));
DEBUG_ONLY(jstart = jb;)
if (JRT_HISTREC == rectype)
@@ -484,24 +484,26 @@ STATICFNDEF int repl_tr_endian_convert(unsigned char remote_jnl_ver, uchar_ptr_t
assert(&rec->jrec_null.strm_seqno == &rec->jrec_tcom.strm_seqno);
rec->jrec_null.strm_seqno = GTM_BYTESWAP_64(rec->jrec_null.strm_seqno);
}
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype))
{
- /* This code will need changes in case the jnl-ver changes from V23 to V24 so add an assert to
+ /* This code will need changes in case the jnl-ver changes from V24 to V25 so add an assert to
* alert to that possibility. Once the code is fixed for the new jnl format, change the assert
* to reflect the new latest jnl-ver.
*/
- assert(JNL_VER_THIS == V23_JNL_VER);
+ assert(JNL_VER_THIS == V24_JNL_VER);
/* To better understand the logic below (particularly the use of hardcoded offsets), see comment
* in repl_filter.c (search for "struct_jrec_upd layout" for the various jnl versions we support).
*/
if (V22_JNL_VER <= remote_jnl_ver)
{ /* byte-swap update_num */
assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
+ assert(&rec->jrec_set_kill.update_num == &rec->jrec_lgtrig.update_num);
rec->jrec_set_kill.update_num = GTM_BYTESWAP_32(rec->jrec_set_kill.update_num);
/* No need to byte-swap num_participants as it is not used by the update process */
/* Get pointer to mumps_node */
keystr = (jnl_string *)&rec->jrec_set_kill.mumps_node;
assert(keystr == (jnl_string *)&rec->jrec_ztworm.ztworm_str);
+ assert(keystr == (jnl_string *)&rec->jrec_lgtrig.lgtrig_str);
} else if (V19_JNL_VER <= remote_jnl_ver)
{ /* byte-swap update_num */
ptr = (unsigned char *)rec + 32; /* is offset of update_num in V19 struct_jrec_upd */
@@ -526,6 +528,7 @@ STATICFNDEF int repl_tr_endian_convert(unsigned char remote_jnl_ver, uchar_ptr_t
if (IS_SET(rectype))
{
assert(!IS_ZTWORM(rectype));
+ assert(!IS_LGTRIG(rectype));
/* SET records have a 'value' part which needs to be endian converted */
vallen_ptr = (mstr_len_t *)&keystr->text[keystr->length];
GET_MSTR_LEN(temp_val, vallen_ptr);
@@ -850,21 +853,18 @@ STATICFNDEF int gtmrecv_est_conn(void)
int gtmrecv_alloc_filter_buff(int bufsiz)
{
- unsigned char *old_filter_buff, *free_filter_buff;
+ unsigned char *old_filter_buff;
bufsiz = ROUND_UP2(bufsiz, OS_PAGE_SIZE);
if ((NO_FILTER != gtmrecv_filter) && (repl_filter_bufsiz < bufsiz))
{
REPL_DPRINT3("Expanding filter buff from %d to %d\n", repl_filter_bufsiz, bufsiz);
- free_filter_buff = filterbuff;
old_filter_buff = repl_filter_buff;
- filterbuff = (unsigned char *)malloc(bufsiz + OS_PAGE_SIZE);
- repl_filter_buff = (uchar_ptr_t)ROUND_UP2((unsigned long)filterbuff, OS_PAGE_SIZE);
- if (NULL != free_filter_buff)
+ repl_filter_buff = malloc(bufsiz);
+ if (NULL != old_filter_buff)
{
- assert(NULL != old_filter_buff);
memcpy(repl_filter_buff, old_filter_buff, repl_filter_bufsiz);
- free(free_filter_buff);
+ free(repl_filter_buff);
}
repl_filter_bufsiz = bufsiz;
}
@@ -873,11 +873,10 @@ int gtmrecv_alloc_filter_buff(int bufsiz)
void gtmrecv_free_filter_buff(void)
{
- if (NULL != filterbuff)
+ if (NULL != repl_filter_buff)
{
- assert(NULL != repl_filter_buff);
- free(filterbuff);
- filterbuff = repl_filter_buff = NULL;
+ free(repl_filter_buff);
+ repl_filter_buff = NULL;
repl_filter_bufsiz = 0;
}
}
@@ -1004,7 +1003,7 @@ void gtmrecv_check_and_send_instinfo(repl_needinst_msg_ptr_t need_instinfo_msg,
assert(inst_hdr->lms_group_info.created_time
|| need_instinfo_msg->lms_group_info.created_time || !need_instinfo_msg->is_rootprimary);
assert((is_rcvr_srvr && (NULL != jnlpool_ctl)) || (!is_rcvr_srvr && (NULL == jnlpool_ctl)) || jgbl.onlnrlbk
- || (jgbl.mur_rollback && ANTICIPATORY_FREEZE_AVAILABLE));
+ || (jgbl.mur_rollback && INST_FREEZE_ON_ERROR_POLICY));
/* If this instance is supplementary and the journal pool exists (to indicate whether updates are enabled or not
* which in turn helps us know whether this is an originating instance or not) do some additional checks.
*/
@@ -1037,7 +1036,7 @@ void gtmrecv_check_and_send_instinfo(repl_needinst_msg_ptr_t need_instinfo_msg,
*/
assert((NULL == jnlpool_ctl) || jnlpool_ctl->upd_disabled
|| inst_hdr->is_supplementary && IS_REPL_INST_UUID_NON_NULL(inst_hdr->lms_group_info)
- || jgbl.onlnrlbk || (jgbl.mur_rollback && ANTICIPATORY_FREEZE_AVAILABLE));
+ || jgbl.onlnrlbk || (jgbl.mur_rollback && INST_FREEZE_ON_ERROR_POLICY));
/* Check if primary and secondary are in same LMS group. Otherwise issue error. An exception is if the group info has
* not yet been filled in after instance file creation. In that case, copy the info from primary and skip the error check.
*/
@@ -1567,7 +1566,6 @@ STATICFNDEF void prepare_recvpool_for_write(int datalen, int pre_filter_write_le
SHM_WRITE_MEMORY_BARRIER;
recvpool_ctl->wrapped = TRUE;
}
- assert(buffered_data_len <= recvpool_size);
DO_FLOW_CONTROL(write_loc);
}
@@ -1618,9 +1616,9 @@ STATICFNDEF void process_tr_buff(int msg_type)
{
recvpool_ctl_ptr_t recvpool_ctl;
seq_num log_seqno, recv_jnl_seqno, upd_seqno, diff_seqno;
- uint4 in_size, out_size, out_bufsiz, tot_out_size, upd_read, max_strm_histinfo;
+ uint4 in_size, out_size, upd_read, max_strm_histinfo;
boolean_t filter_pass = FALSE, is_new_histrec, is_repl_cmpc;
- uchar_ptr_t save_buffp, save_filter_buff, in_buff, out_buff;
+ uchar_ptr_t save_buffp, save_filter_buff, in_buff;
int idx, status, num_strm_histinfo;
qw_num msg_total;
repl_old_triple_jnl_t old_triple_content;
@@ -1698,8 +1696,7 @@ STATICFNDEF void process_tr_buff(int msg_type)
repl_log(gtmrecv_log_fp, TRUE, TRUE, "Update process has successfully cleared the backlog\n");
gtmrecv_send_cmp2uncmp = TRUE; /* trigger REPL_CMP2UNCMP message processing */
gtmrecv_poll_actions(data_len, buff_unprocessed, buffp);
- assert(!gtmrecv_send_cmp2uncmp);
- assert(gtmrecv_wait_for_jnl_seqno);
+ assert(repl_connection_reset || (!gtmrecv_send_cmp2uncmp && gtmrecv_wait_for_jnl_seqno));
return;
}
assert(0 == destlen % REPL_MSG_ALIGN);
@@ -1751,29 +1748,37 @@ STATICFNDEF void process_tr_buff(int msg_type)
{ /* Need to pass through filter */
pre_filter_write = write_off;
pre_filter_write_len = write_len;
+ /* If input transaction cannot fit in currently allocated buffer, expand buffer
+ * directly to that needed length hoping this should be enough (minimizes the # of
+ * 50% expansions we do). If this is still not enough (because the filter function
+ * results in bigger sized jnl records) we will then do geometric expansion of this
+ * buffer in the while loop below as much as needed.
+ */
+ if (write_len > repl_filter_bufsiz)
+ {
+ gtmrecv_free_filter_buff();
+ gtmrecv_alloc_filter_buff(write_len);
+ }
if (gtmrecv_filter & INTERNAL_FILTER)
{
in_buff = recvpool.recvdata_base + write_off;
in_size = write_len;
- out_buff = repl_filter_buff;
- out_bufsiz = repl_filter_bufsiz;
- tot_out_size = 0;
while (SS_NORMAL != (status =
repl_filter_old2cur[remote_side->jnl_ver - JNL_VER_EARLIEST_REPL](
- in_buff, &in_size, out_buff, &out_size, out_bufsiz))
+ in_buff, &in_size, repl_filter_buff, &out_size, repl_filter_bufsiz))
&& (EREPL_INTLFILTER_NOSPC == repl_errno))
- {
- save_filter_buff = repl_filter_buff;
+ { /* We ran out of space in current buffer. We can try and use the transformed
+ * records as is and resume transformation from where the space-issue occurred
+ * but the transformation function might rely on seeing the entire transaction
+ * context in one shot so better not to take a risk. So free old buffer and
+ * allocate new buffer and redo transformation from scratch.
+ */
+ gtmrecv_free_filter_buff();
gtmrecv_alloc_filter_buff(repl_filter_bufsiz + (repl_filter_bufsiz >> 1));
- in_buff += in_size;
- in_size = (uint4)(pre_filter_write_len -
- (in_buff - recvpool.recvdata_base - write_off));
- out_bufsiz = (uint4)(repl_filter_bufsiz - (out_buff - save_filter_buff) - out_size);
- out_buff = repl_filter_buff + (out_buff - save_filter_buff) + out_size;
- tot_out_size += out_size;
+ in_size = write_len; /* just in case in_size was modified */
}
if (SS_NORMAL == status)
- write_len = tot_out_size + out_size;
+ write_len = out_size;
else
{
assert(EREPL_INTLFILTER_SECNODZTRIGINTP == repl_errno);
@@ -1795,11 +1800,7 @@ STATICFNDEF void process_tr_buff(int msg_type)
assertpro(repl_errno != repl_errno);
}
} else
- {
- if (write_len > repl_filter_bufsiz)
- gtmrecv_alloc_filter_buff(write_len);
memcpy(repl_filter_buff, recvpool.recvdata_base + write_off, write_len);
- }
assert(write_len <= repl_filter_bufsiz);
GTMTRIG_ONLY(
if ((unsigned char)V19_JNL_VER <= remote_side->jnl_ver)
@@ -1808,9 +1809,10 @@ STATICFNDEF void process_tr_buff(int msg_type)
DBG_VERIFY_TR_BUFF_SORTED(repl_filter_buff, write_len);
}
)
- if ((gtmrecv_filter & EXTERNAL_FILTER) &&
- (SS_NORMAL != (status = repl_filter(recvpool_ctl->jnl_seqno, repl_filter_buff, (int*)&write_len,
- repl_filter_bufsiz))))
+ if ((gtmrecv_filter & EXTERNAL_FILTER)
+ && (SS_NORMAL !=
+ (status = repl_filter(recvpool_ctl->jnl_seqno, &repl_filter_buff,
+ (int*)&write_len, &repl_filter_bufsiz))))
repl_filter_error(recvpool_ctl->jnl_seqno, status);
GTMTRIG_ONLY(
/* Ensure that the external filter has not disturbed the sorted sequence of the
diff --git a/sr_unix/gtmsecshr.c b/sr_unix/gtmsecshr.c
index 8d37b2e..42e536e 100644
--- a/sr_unix/gtmsecshr.c
+++ b/sr_unix/gtmsecshr.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -78,8 +78,7 @@
#include "gtmio.h"
#include "file_head_read.h"
#include "file_head_write.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
#include "hashtab.h"
#include "fork_init.h"
@@ -87,6 +86,7 @@
# include "gtm_icu_api.h"
# include "gtm_utf8.h"
#endif
+#include "getjobnum.h"
#define execname "gtmsecshr" /* this is what this executable is supposed to be called. A different name is verboten */
#define intent_open "for open" /* FLUSH_DB_IPCS_INFO types */
@@ -104,6 +104,7 @@ GBLREF uint4 process_id;
GBLREF boolean_t need_core;
GBLREF boolean_t first_syslog; /* Defined in util_output.c */
GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
LITREF char gtm_release_name[];
LITREF int4 gtm_release_name_len;
@@ -224,9 +225,7 @@ int main(int argc, char_ptr_t argv[])
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- gtm_imagetype_init(GTMSECSHR_IMAGE); /* Side-effect : Sets skip_dbtriggers = TRUE if platorm lacks trigger support */
- gtm_wcswidth_fnptr = NULL;
- gtm_env_init(); /* read in all environment variables */
+ common_startup_init(GTMSECSHR_IMAGE); /* Side-effect : Sets skip_dbtriggers = TRUE if platorm lacks trigger support */
err_init(gtmsecshr_cond_hndlr);
gtmsecshr_init(argv, &rundir, &rundir_len);
timer_id = (TID)main;
@@ -325,8 +324,6 @@ void gtmsecshr_init(char_ptr_t argv[], char **rundir, int *rundir_len)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- process_id = getpid();
- set_blocksig();
/* Before priv escalation need to understand how/where we were invoked in terms of module path and name.
*
* Steps:
@@ -486,7 +483,7 @@ void gtmsecshr_init(char_ptr_t argv[], char **rundir, int *rundir_len)
CLOSELOG();
ENABLE_INTERRUPTS(INTRPT_IN_LOG_FUNCTION);
first_syslog = TRUE;
- FORK(pid); /* Timers have not been initialized, no need to do FORK_CLEAN; BYPASSOK */
+ FORK(pid);
if (0 > pid)
{ /* Fork failed */
save_errno = errno;
@@ -497,8 +494,9 @@ void gtmsecshr_init(char_ptr_t argv[], char **rundir, int *rundir_len)
/* This is the original process - it dies quietly (no exit handler of any sort) to isolate us */
_exit(EXIT_SUCCESS);
/****** We are now in the (isolated) child process ******/
- process_id = getpid();
+ getjobnum();
pid = getsid(process_id);
+ gtm_dist_ok_to_use = TRUE;
if ((pid != process_id) && ((pid_t)-1 == setsid()))
{
save_errno = errno;
@@ -1058,7 +1056,7 @@ int validate_receiver(gtmsecshr_mesg *buf, char *rundir, int rundir_len, int sav
ppptr = procpath;
MEMCPY_LIT(procpath, PROCPATH_PREFIX);
ppptr += STRLEN(PROCPATH_PREFIX);
- ppptr = i2asc(ppptr, buf->mesg.id);
+ ppptr = (char*)i2asc((uchar_ptr_t)ppptr, buf->mesg.id);
ppptr_save = ppptr; /* Save where adding cmdline so can replace if need to move to check #2 */
memcpy(ppptr, PROCPATH_CMDLSUFFIX, SIZEOF(PROCPATH_CMDLSUFFIX)); /* Copy includes terminating null of literal */
procstrm = Fopen(procpath, "r");
diff --git a/sr_unix/gtmsecshr_sock_init.c b/sr_unix/gtmsecshr_sock_init.c
index 2f13983..cc4affd 100644
--- a/sr_unix/gtmsecshr_sock_init.c
+++ b/sr_unix/gtmsecshr_sock_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -27,6 +27,7 @@
#include "io.h"
#include "error.h"
#include "gtmsecshr.h"
+#include "gtmimagename.h"
#include "iosp.h"
#include "send_msg.h"
#include "getjobnum.h"
@@ -44,7 +45,10 @@ GBLREF mstr gtmsecshr_pathname;
GBLREF boolean_t gtmsecshr_sock_init_done;
GBLREF uint4 process_id;
GBLREF int gtmsecshr_sockfd;
-GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
+
+LITREF gtmImageName gtmImageNames[];
static char gtmsecshr_sockpath[GTM_PATH_MAX];
static char gtmsecshr_path[GTM_PATH_MAX];
@@ -58,6 +62,7 @@ unsigned char *mypid2ascx(unsigned char *, pid_t);
# define EXACT_SIZE_SOCKNAME
#endif
+error_def(ERR_GTMDISTUNVERIF);
error_def(ERR_GTMSECSHRSOCKET);
error_def(ERR_LOGTOOLONG);
error_def(ERR_TEXT);
@@ -72,6 +77,13 @@ int4 gtmsecshr_pathname_init(int caller, char *execpath, int execpathln)
if (!process_id)
getjobnum();
+ if (!gtm_dist_ok_to_use)
+ if (SERVER == caller)
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, STRLEN(gtm_dist), gtm_dist,
+ gtmImageNames[image_type].imageNameLen, gtmImageNames[image_type].imageName);
+ else
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, STRLEN(gtm_dist), gtm_dist,
+ gtmImageNames[image_type].imageNameLen, gtmImageNames[image_type].imageName);
secshrsock_lognam.addr = GTMSECSHR_SOCK_DIR;
secshrsock_lognam.len = SIZEOF(GTMSECSHR_SOCK_DIR) - 1;
/* Get the maximum size of the path excluding the socket filename */
@@ -134,25 +146,12 @@ int4 gtmsecshr_pathname_init(int caller, char *execpath, int execpathln)
} else
{ /* Discover path name */
len = STRLEN(gtm_dist);
- if (!len)
- {
- gtmsecshr_pathname.len = 0;
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_GTMSECSHRSOCKET, 3,
- RTS_ERROR_STRING("Caller"), process_id, ERR_TEXT, 2,
- RTS_ERROR_LITERAL("Environment variable gtm_dist pointing to an invalid path"));
- ret_status = INVLOGNAME;
-
- }
- else {
- memcpy(gtmsecshr_path, gtm_dist, len);
- gtmsecshr_path[len] = '/';
- memcpy(gtmsecshr_path + len + 1, GTMSECSHR_EXECUTABLE, STRLEN(GTMSECSHR_EXECUTABLE));
- gtmsecshr_pathname.addr = gtmsecshr_path;
- gtmsecshr_pathname.len = len + 1 + STRLEN(GTMSECSHR_EXECUTABLE);
- if (GTM_PATH_MAX <= gtmsecshr_pathname.len)
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2,
- RTS_ERROR_LITERAL("gtmsecshr path too long"));
- }
+ memcpy(gtmsecshr_path, gtm_dist, len);
+ gtmsecshr_path[len] = '/';
+ memcpy(gtmsecshr_path + len + 1, GTMSECSHR_EXECUTABLE, STRLEN(GTMSECSHR_EXECUTABLE));
+ gtmsecshr_pathname.addr = gtmsecshr_path;
+ gtmsecshr_pathname.len = len + 1 + STRLEN(GTMSECSHR_EXECUTABLE);
+ assertpro(GTM_PATH_MAX > gtmsecshr_pathname.len);
gtmsecshr_path[gtmsecshr_pathname.len] = '\0';
}
/* We have different project id here. This guarantees to avoid deadlock, if only one gtm installation is there */
diff --git a/sr_unix/gtmsecshr_wrapper.c b/sr_unix/gtmsecshr_wrapper.c
index 79bda13..71560dc 100644
--- a/sr_unix/gtmsecshr_wrapper.c
+++ b/sr_unix/gtmsecshr_wrapper.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2008, 2013 Fidelity Information Services, Inc *
+ * Copyright 2008, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -100,6 +100,31 @@ extern char **environ;
#define ERR_SECSHRWRITABLE \
"%%GTM-E-SECSHRWRITABLE, %s writable. gtmsecshr will not be started\n"
+/*
+Make sure these are synced with the above. We need this comment for the InfoHub tools to generate message
+information for gtmsecshr_wrapper.c, since it does not have a stand-alone .msg file.
+
+ .FACILITY GTMSECSHRINIT,251/PREFIX=ERR_
+
+SECSHRCHDIRFAILED <chdir failed on !AD, errno !UL. gtmsecshr will not be started>/error/fao=3!/ansi=0
+SECSHRCLEARENVFAILED <clearenv failed. gtmsecshr will not be started>/error/fao=0!/ansi=0
+SECSHREXECLFAILED <execl of !AD failed>/error/fao=2!/ansi=0
+SECSHRGTMDBGLVL2LONG <gtmdbglvl env var too long. gtmsecshr will not be started>/error/fao=0!/ansi=0
+SECSHRGTMDIST2LONG <gtm_dist env var too long. gtmsecshr will not be started>/error/fao=0!/ansi=0
+SECSHRGTMTMP2LONG <gtm_tmp env var too long. gtmsecshr will not be started>/error/fao=0!/ansi=0
+SECSHRNOGTMDIST <gtm_dist env var does not exist. gtmsecshr will not be started>/error/fao=0!/ansi=0
+SECSHRNOTOWNEDBYROOT <!AD not owned by root. gtmsecshr will not be started>/error/fao=3!/ansi=0
+SECSHRNOTSETUID <!AD not set-uid. gtmsecshr will not be started>/error/fao=2!/ansi=0
+SECSHRPERMINCRCT <!AD permissions incorrect (0!UL). gtmsecshr will not be started>/error/fao=3!/ansi=0
+SECSHRSETGTMDISTFAILED <setenv for gtm_dist failed. gtmsecshr will not be started>/error/fao=0!/ansi=0
+SECSHRSETGTMTMPFAILED <setenv for gtm_tmp failed. gtmsecshr will not be started>/error/fao=0!/ansi=0
+SECSHRSETUIDFAILED <setuid failed. gtmsecshr will not be started>/error/fao=0!/ansi=0
+SECSHRSTATFAILED <stat failed on !AD, errno !UL. gtmsecshr will not be started>/error/fao=3!/ansi=0
+SECSHRWRITABLE <!AD writable. gtmsecshr will not be started>/error/fao=2!/ansi=0
+! the following line stops getmsginfo.m
+ .end
+*/
+
int gtm_setenv(char * env_var_name, char * env_var_val, int overwrite);
int gtm_setenv(char * env_var_name, char * env_var_val, int overwrite)
{ /* The overwrite parameter is not used. In our case we always want to set the value */
diff --git a/sr_unix/gtmsource.c b/sr_unix/gtmsource.c
index b308724..dc6a7f5 100644
--- a/sr_unix/gtmsource.c
+++ b/sr_unix/gtmsource.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -183,7 +183,7 @@ int gtmsource()
/* Set "child_server_running" to FALSE before forking off child. Wait for it to be set to TRUE by the child. */
gtmsource_local = jnlpool.gtmsource_local;
gtmsource_local->child_server_running = FALSE;
- FORK_CLEAN(pid);
+ FORK(pid);
if (0 > pid)
{
save_errno = errno;
@@ -439,10 +439,7 @@ int gtmsource()
if (SS_NORMAL == (status = repl_filter_init(gtmsource_local->filter_cmd)))
gtmsource_filter |= EXTERNAL_FILTER;
else
- {
- if (EREPL_FILTERSTART_EXEC == repl_errno)
- gtmsource_exit(ABNORMAL_SHUTDOWN);
- }
+ gtmsource_exit(ABNORMAL_SHUTDOWN);
}
gtmsource_process();
/* gtmsource_process returns only when mode needs to be changed to PASSIVE */
diff --git a/sr_unix/gtmsource_end.c b/sr_unix/gtmsource_end.c
index bf84438..a9dc7e5 100644
--- a/sr_unix/gtmsource_end.c
+++ b/sr_unix/gtmsource_end.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc *
+ * Copyright 2006, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -88,7 +88,7 @@ int gtmsource_end1(boolean_t auto_shutdown)
jnlpool_strm_seqno[idx] = jnlpool.jnlpool_ctl->strm_seqno[idx];
jnlpool.gtmsource_local->gtmsource_pid = 0;
jnlpool.gtmsource_local->gtmsource_state = GTMSOURCE_DUMMY_STATE;
- if (!auto_shutdown && !ANTICIPATORY_FREEZE_AVAILABLE)
+ if (!auto_shutdown && !CUSTOM_ERRORS_LOADED)
{ /* Detach from journal pool */
JNLPOOL_SHMDT(status, save_errno);
if (0 > status)
diff --git a/sr_unix/gtmsource_process.c b/sr_unix/gtmsource_process.c
index 81b3172..07d8f03 100644
--- a/sr_unix/gtmsource_process.c
+++ b/sr_unix/gtmsource_process.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc.*
+ * Copyright 2006, 2014 Fidelity Information Services, Inc.*
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -252,6 +252,7 @@ static void repl_tr_endian_convert(repl_msg_ptr_t send_msgp, int send_tr_len, se
buflen = send_msgp->len - REPL_MSG_HDRLEN;
remaining_len = send_tr_len;
/* QWASSIGN(good_seqno, seq_num_zero); */
+ status = 0;
while (0 < remaining_len)
{
jlen = buflen;
@@ -273,7 +274,7 @@ static void repl_tr_endian_convert(repl_msg_ptr_t send_msgp, int send_tr_len, se
break;
}
assert(!IS_ZTP(rectype));
- assert(IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype) || (JRT_TCOM == rectype) || (JRT_NULL == rectype));
+ assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype) || (JRT_TCOM == rectype) || (JRT_NULL == rectype));
/* endian convert the suffix fields. Only backptr needs endian conversion as the other field - suffix_code
* is 8 bit.
*/
@@ -288,11 +289,13 @@ static void repl_tr_endian_convert(repl_msg_ptr_t send_msgp, int send_tr_len, se
assert(&rec->jrec_null.strm_seqno == &rec->jrec_set_kill.strm_seqno);
assert(&rec->jrec_null.strm_seqno == &rec->jrec_tcom.strm_seqno);
rec->jrec_null.strm_seqno = GTM_BYTESWAP_64(rec->jrec_null.strm_seqno);
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype))
{
keystr = (jnl_string *)&rec->jrec_set_kill.mumps_node;
assert(keystr == (jnl_string *)&rec->jrec_ztworm.ztworm_str);
+ assert(keystr == (jnl_string *)&rec->jrec_lgtrig.lgtrig_str);
assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
+ assert(&rec->jrec_set_kill.update_num == &rec->jrec_lgtrig.update_num);
rec->jrec_set_kill.update_num = GTM_BYTESWAP_32(rec->jrec_set_kill.update_num);
/* From V19 onwards, the 'length' field is divided into 8 bit 'nodeflags' and 24 bit 'length'
* fields.
@@ -300,13 +303,13 @@ static void repl_tr_endian_convert(repl_msg_ptr_t send_msgp, int send_tr_len, se
keylen = keystr->length;
nodeflags_keylen = *(jnl_str_len_t *)keystr;
*(jnl_str_len_t *)keystr = GTM_BYTESWAP_32(nodeflags_keylen);
- if (IS_SET(rectype) || IS_ZTWORM(rectype))
- { /* SET and ZTWORM records have a 'value' part which needs to be endian converted */
+ if (IS_SET(rectype) || IS_ZTWORM(rectype) || IS_LGTRIG(rectype))
+ { /* SET/ZTWORM/LGTRIG records have a 'key/value' part whose length needs endian conversion */
vallen_ptr = (mstr_len_t *)&keystr->text[keylen];
GET_MSTR_LEN(temp_val, vallen_ptr);
temp_val = GTM_BYTESWAP_32(temp_val);
PUT_MSTR_LEN(vallen_ptr, temp_val);
- /* The actual 'value' itself is a character array and hence needs no endian conversion */
+ /* The 'key/value' itself is a character array and hence needs no endian conversion */
}
} else if (JRT_TCOM == rectype)
{
@@ -1481,11 +1484,11 @@ int gtmsource_process(void)
if (gtmsource_filter & INTERNAL_FILTER)
{
in_buff = gtmsource_msgp->msg;
- in_buflen = data_len; /* size of the first journal record in the converted buffer */
+ in_buflen = data_len; /* jrec size of the FIRST SEQNO in the converted buffer */
out_buffmsg = repl_filter_buff;
out_buff = out_buffmsg + REPL_MSG_HDRLEN;
out_bufsiz = repl_filter_bufsiz - REPL_MSG_HDRLEN;
- remaining_len = tot_tr_len;
+ remaining_len = tot_tr_len; /* jrec size of ALL SEQNOs ( >= 1) in buffer */
while (JREC_PREFIX_SIZE <= remaining_len)
{
filter_seqno = ((struct_jrec_null *)(in_buff))->jnl_seqno;
diff --git a/sr_unix/gtmsource_process_ops.c b/sr_unix/gtmsource_process_ops.c
index 84cb227..8646799 100644
--- a/sr_unix/gtmsource_process_ops.c
+++ b/sr_unix/gtmsource_process_ops.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc *
+ * Copyright 2006, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -128,8 +128,6 @@ error_def(ERR_TEXT);
error_def(ERR_TLSCONVSOCK);
error_def(ERR_TLSHANDSHAKE);
-static unsigned char *tcombuff, *msgbuff, *cmpmsgbuff, *filterbuff;
-
int gtmsource_est_conn()
{
char print_msg[1024], msg_str[1024], *errmsg;
@@ -305,42 +303,38 @@ int gtmsource_est_conn()
int gtmsource_alloc_tcombuff(void)
{ /* Allocate buffer for TCOM, ZTCOM records */
- if (NULL == tcombuff)
+ if (NULL == gtmsource_tcombuff_start)
{
assert(NULL == gtmsource_tcombuff_start);
- tcombuff = (unsigned char *)malloc(gd_header->n_regions * TCOM_RECLEN + OS_PAGE_SIZE);
- gtmsource_tcombuff_start = (unsigned char *)ROUND_UP2((unsigned long)tcombuff, OS_PAGE_SIZE);
+ gtmsource_tcombuff_start = (unsigned char *)malloc(gd_header->n_regions * TCOM_RECLEN);
}
return (SS_NORMAL);
}
void gtmsource_free_tcombuff(void)
{
- if (NULL != tcombuff)
+ if (NULL != gtmsource_tcombuff_start)
{
- free(tcombuff);
- tcombuff = gtmsource_tcombuff_start = NULL;
+ free(gtmsource_tcombuff_start);
+ gtmsource_tcombuff_start = NULL;
}
return;
}
int gtmsource_alloc_filter_buff(int bufsiz)
{
- unsigned char *old_filter_buff, *free_filter_buff;
+ unsigned char *old_filter_buff;
- bufsiz = ROUND_UP2(bufsiz, OS_PAGE_SIZE);
- if (gtmsource_filter != NO_FILTER && bufsiz > repl_filter_bufsiz)
+ if ((NO_FILTER != gtmsource_filter) && (bufsiz > repl_filter_bufsiz))
{
REPL_DPRINT3("Expanding filter buff from %d to %d\n", repl_filter_bufsiz, bufsiz);
- free_filter_buff = filterbuff;
old_filter_buff = repl_filter_buff;
- filterbuff = (unsigned char *)malloc(bufsiz + OS_PAGE_SIZE);
- repl_filter_buff = (unsigned char *)ROUND_UP2((unsigned long)filterbuff, OS_PAGE_SIZE);
- if (NULL != free_filter_buff)
+ repl_filter_buff = (unsigned char *)malloc(bufsiz);
+ if (NULL != old_filter_buff)
{
assert(NULL != old_filter_buff);
memcpy(repl_filter_buff, old_filter_buff, repl_filter_bufsiz);
- free(free_filter_buff);
+ free(old_filter_buff);
}
repl_filter_bufsiz = bufsiz;
}
@@ -349,11 +343,11 @@ int gtmsource_alloc_filter_buff(int bufsiz)
void gtmsource_free_filter_buff(void)
{
- if (NULL != filterbuff)
+ if (NULL != repl_filter_buff)
{
assert(NULL != repl_filter_buff);
- free(filterbuff);
- filterbuff = repl_filter_buff = NULL;
+ free(repl_filter_buff);
+ repl_filter_buff = NULL;
repl_filter_bufsiz = 0;
}
}
@@ -361,34 +355,28 @@ void gtmsource_free_filter_buff(void)
int gtmsource_alloc_msgbuff(int maxbuffsize, boolean_t discard_oldbuff)
{ /* Allocate message buffer */
repl_msg_ptr_t oldmsgp;
- unsigned char *free_msgp;
assert(MIN_REPL_MSGLEN < maxbuffsize);
- maxbuffsize = ROUND_UP2(maxbuffsize, OS_PAGE_SIZE);
if ((maxbuffsize > gtmsource_msgbufsiz) || (NULL == gtmsource_msgp))
{
REPL_DPRINT3("Expanding message buff from %d to %d\n", gtmsource_msgbufsiz, maxbuffsize);
- free_msgp = msgbuff;
oldmsgp = gtmsource_msgp;
- msgbuff = (unsigned char *)malloc(maxbuffsize + OS_PAGE_SIZE);
- gtmsource_msgp = (repl_msg_ptr_t)ROUND_UP2((unsigned long)msgbuff, OS_PAGE_SIZE);
- if (NULL != free_msgp)
+ gtmsource_msgp = (repl_msg_ptr_t)malloc(maxbuffsize);
+ if (NULL != oldmsgp)
{ /* Copy existing data */
- assert(NULL != oldmsgp);
if (!discard_oldbuff)
memcpy((unsigned char *)gtmsource_msgp, (unsigned char *)oldmsgp, gtmsource_msgbufsiz);
- free(free_msgp);
+ free(oldmsgp);
}
gtmsource_msgbufsiz = maxbuffsize;
if (ZLIB_CMPLVL_NONE != gtm_zlib_cmp_level)
{ /* Compression is enabled. Allocate parallel buffers to hold compressed journal records.
* Allocate extra space just in case compression actually expands the data (needed only in rare cases).
*/
- free_msgp = cmpmsgbuff;
- cmpmsgbuff = (unsigned char *)malloc((maxbuffsize * MAX_CMP_EXPAND_FACTOR) + OS_PAGE_SIZE);
- gtmsource_cmpmsgp = (repl_msg_ptr_t)ROUND_UP2((unsigned long)cmpmsgbuff, OS_PAGE_SIZE);
- if (NULL != free_msgp)
- free(free_msgp);
+ oldmsgp = gtmsource_cmpmsgp;
+ gtmsource_cmpmsgp = (repl_msg_ptr_t)malloc(maxbuffsize * MAX_CMP_EXPAND_FACTOR);
+ if (NULL != oldmsgp)
+ free(oldmsgp);
gtmsource_cmpmsgbufsiz = (maxbuffsize * MAX_CMP_EXPAND_FACTOR);
}
gtmsource_alloc_filter_buff(gtmsource_msgbufsiz);
@@ -398,18 +386,15 @@ int gtmsource_alloc_msgbuff(int maxbuffsize, boolean_t discard_oldbuff)
void gtmsource_free_msgbuff(void)
{
- if (NULL != msgbuff)
+ if (NULL != gtmsource_msgp)
{
- assert(NULL != gtmsource_msgp);
- free(msgbuff);
- msgbuff = NULL;
+ free(gtmsource_msgp);
gtmsource_msgp = NULL;
gtmsource_msgbufsiz = 0;
if (ZLIB_CMPLVL_NONE != gtm_zlib_cmp_level)
{ /* Compression is enabled. Free up compression buffer as well. */
assert(NULL != gtmsource_cmpmsgp);
- free(cmpmsgbuff);
- cmpmsgbuff = NULL;
+ free(gtmsource_cmpmsgp);
gtmsource_cmpmsgp = NULL;
gtmsource_cmpmsgbufsiz = 0;
}
diff --git a/sr_unix/gtmsource_readfiles.c b/sr_unix/gtmsource_readfiles.c
index 313d75f..9ed8342 100644
--- a/sr_unix/gtmsource_readfiles.c
+++ b/sr_unix/gtmsource_readfiles.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc *
+ * Copyright 2006, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -17,7 +17,8 @@
#include "gtm_ipc.h"
#include "gtm_socket.h"
#include "gtm_inet.h"
-#include <sys/un.h>
+#include "gtm_un.h"
+
#include <sys/time.h>
#include <errno.h>
#include "gtm_fcntl.h"
@@ -70,6 +71,23 @@
/* Get journal end of data, adjusted if file not virtually truncated by recover/rollback */
#define REAL_END_OF_DATA(FC) (FC->jfh->prev_recov_end_of_data ? FC->jfh->end_of_data : FC->jfh->end_of_data + EOF_RECLEN)
+#define DO_EOF_ADDR_CHECK FALSE
+#define SKIP_EOF_ADDR_CHECK TRUE
+
+/* Callers of this macro ensure that the maximum seqno which can be found until offset MAX_SEQNO_EOF_ADDR is MAX_SEQNO. */
+#define CTL_SET_MAX_SEQNO(CTL, MAX_SEQNO, MAX_SEQNO_ADDR, MAX_SEQNO_EOF_ADDR, SKIP_EOF_ADDR_CHECK) \
+{ \
+ assert(MAX_SEQNO_ADDR <= MAX_SEQNO_EOF_ADDR); \
+ assert(SKIP_EOF_ADDR_CHECK || (MAX_SEQNO_EOF_ADDR <= CTL->repl_buff->fc->eof_addr)); \
+ assert(ctl->max_seqno <= MAX_SEQNO); \
+ ctl->max_seqno = MAX_SEQNO; \
+ assert(ctl->max_seqno_dskaddr <= MAX_SEQNO_ADDR); \
+ ctl->max_seqno_dskaddr = MAX_SEQNO_ADDR; \
+ assert(MAX_SEQNO_EOF_ADDR >= MAX_SEQNO_ADDR); \
+ assert(ctl->max_seqno_eof_addr <= MAX_SEQNO_EOF_ADDR); \
+ ctl->max_seqno_eof_addr = MAX_SEQNO_EOF_ADDR; \
+}
+
GBLREF unsigned char *gtmsource_tcombuff_start;
GBLREF jnlpool_addrs jnlpool;
GBLREF repl_ctl_element *repl_ctl_list;
@@ -81,6 +99,7 @@ GBLREF gd_region *gv_cur_region;
GBLREF FILE *gtmsource_log_fp;
GBLREF gtmsource_state_t gtmsource_state;
GBLREF uint4 process_id;
+GBLREF uint4 heartbeat_counter;
LITREF char *jnl_file_state_lit[];
@@ -251,8 +270,8 @@ static int repl_next(repl_buff_t *rb)
MEMCPY_LIT(err_string, READ_ERR_STR);
else
MEMCPY_LIT(err_string, UNKNOWN_ERR_STR);
- rts_error(VARLSTCNT(9) ERR_REPLFILIOERR, 2, backctl->jnl_fn_len, backctl->jnl_fn,
- ERR_TEXT, 2, LEN_AND_STR(err_string), status);
+ rts_error_csa(CSA_ARG(&FILE_INFO(backctl->reg)->s_addrs) VARLSTCNT(9) ERR_REPLFILIOERR, 2,
+ backctl->jnl_fn_len, backctl->jnl_fn, ERR_TEXT, 2, LEN_AND_STR(err_string), status);
}
}
maxreclen = (uint4)(((b->base + REPL_BLKSIZE(rb)) - b->recbuff) - b->buffremaining);
@@ -266,12 +285,13 @@ static int repl_next(repl_buff_t *rb)
{
rec = ((jnl_record *)(b->recbuff));
rectype = (enum jnl_record_type)rec->prefix.jrec_type;
- if (IS_SET_KILL_ZKILL_ZTRIG_ZTWORM(rectype))
+ if (IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype))
{
assert(!IS_ZTP(rectype));
keystr = (jnl_string *)&rec->jrec_set_kill.mumps_node;
- /* Assert that ZTWORMHOLE type record too has same layout as KILL/SET */
+ /* Assert that ZTWORMHOLE and LGTRIG type record too has same layout as KILL/SET */
assert((sm_uc_ptr_t)keystr == (sm_uc_ptr_t)&rec->jrec_ztworm.ztworm_str);
+ assert((sm_uc_ptr_t)keystr == (sm_uc_ptr_t)&rec->jrec_lgtrig.lgtrig_str);
MUR_DECRYPT_LOGICAL_RECS(keystr, rec->prefix.forwptr, backctl->encr_key_handle, gtmcrypt_errno);
if (0 != gtmcrypt_errno)
GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, rts_error, backctl->jnl_fn_len, backctl->jnl_fn);
@@ -293,7 +313,6 @@ static int repl_next(repl_buff_t *rb)
static int open_prev_gener(repl_ctl_element **old_ctl, repl_ctl_element *ctl, seq_num read_seqno)
{
-
if (0 == ctl->repl_buff->fc->jfh->prev_jnl_file_name_length ||
QWLE(ctl->repl_buff->fc->jfh->start_seqno, read_seqno))
{
@@ -310,16 +329,16 @@ static int open_prev_gener(repl_ctl_element **old_ctl, repl_ctl_element *ctl, se
(*old_ctl)->prev->next = *old_ctl;
(*old_ctl)->next->prev = *old_ctl;
first_read(*old_ctl);
- if ((*old_ctl)->file_state == JNL_FILE_OPEN)
+ assertpro((JNL_FILE_OPEN == (*old_ctl)->file_state) || (JNL_FILE_UNREAD == (*old_ctl)->file_state));
+ if (JNL_FILE_OPEN == (*old_ctl)->file_state)
{
(*old_ctl)->file_state = JNL_FILE_CLOSED;
REPL_DPRINT2("open_prev_gener : %s jnl file marked closed\n", (*old_ctl)->jnl_fn);
- } else if ((*old_ctl)->file_state == JNL_FILE_UNREAD)
+ } else if (JNL_FILE_UNREAD == (*old_ctl)->file_state)
{
(*old_ctl)->file_state = JNL_FILE_EMPTY;
REPL_DPRINT2("open_prev_gener : %s jnl file marked empty\n", (*old_ctl)->jnl_fn);
- } else
- GTMASSERT;
+ }
return (1);
}
@@ -374,7 +393,7 @@ static int open_newer_gener_jnlfiles(gd_region *reg, repl_ctl_element *reg_ctl_e
jnl_fn[jnl_fn_len] = '\0';
if ('\0' == jnl_fn[0])
{ /* prev link has been cut, can't follow path back from latest generation jnlfile to the latest we had opened */
- rts_error(VARLSTCNT(4) ERR_NOPREVLINK, 2, new_ctl->jnl_fn_len, new_ctl->jnl_fn);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_NOPREVLINK, 2, new_ctl->jnl_fn_len, new_ctl->jnl_fn);
}
if (is_gdid_file_identical(reg_ctl_end_id, jnl_fn, jnl_fn_len))
break;
@@ -393,9 +412,11 @@ static int open_newer_gener_jnlfiles(gd_region *reg, repl_ctl_element *reg_ctl_e
}
/* Except the latest generation, mark the newly opened future generations CLOSED, or EMPTY.
* We assume that when a new file is opened, the previous generation has been flushed to disk fully.
- C9M06-999999 */
+ * C9M06-999999.
+ */
for (ctl = reg_ctl_end, n = nopen; n; n--, ctl = ctl->next)
{
+ assertpro((JNL_FILE_UNREAD == ctl->file_state) || (JNL_FILE_OPEN == ctl->file_state));
if (ctl->file_state == JNL_FILE_UNREAD)
first_read(ctl);
else if (ctl->file_state == JNL_FILE_OPEN)
@@ -403,10 +424,9 @@ static int open_newer_gener_jnlfiles(gd_region *reg, repl_ctl_element *reg_ctl_e
if (update_max_seqno_info(ctl) != SS_NORMAL)
{
assert(repl_errno == EREPL_JNLEARLYEOF);
- GTMASSERT; /* Program bug */
+ assertpro(FALSE); /* Program bug */
}
- } else
- GTMASSERT;
+ }
if (ctl->file_state == JNL_FILE_UNREAD)
{
ctl->file_state = JNL_FILE_EMPTY;
@@ -449,7 +469,7 @@ static int update_eof_addr(repl_ctl_element *ctl, int *eof_change)
{
F_READ_BLK_ALIGNED(fc->fd, 0, fc->jfh, REAL_JNL_HDR_LEN, status);
if (SS_NORMAL != status)
- rts_error(VARLSTCNT(9) ERR_REPLFILIOERR, 2, ctl->jnl_fn_len, ctl->jnl_fn,
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_REPLFILIOERR, 2, ctl->jnl_fn_len, ctl->jnl_fn,
ERR_TEXT, 2, LEN_AND_LIT("Error in reading jfh in update_eof_addr"), status);
REPL_DPRINT2("Update EOF : Jnl file hdr refreshed from file for %s\n", ctl->jnl_fn);
ctl->eof_addr_final = TRUE; /* No more updates to fc->eof_addr for this journal file */
@@ -516,8 +536,8 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
repl_buff_t *rb;
repl_buff_desc *b;
repl_file_control_t *fc;
- uint4 dskread, stop_at;
- boolean_t max_seqno_found;
+ uint4 dskread, max_seqno_eof_addr, stop_at;
+ boolean_t eof_addr_final, max_seqno_found;
uint4 max_seqno_addr;
seq_num max_seqno, reg_seqno;
int status;
@@ -542,8 +562,16 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
return (SS_NORMAL);
}
# endif
- if (JNL_FILE_FIRST_RECORD == fc->eof_addr)
- { /* Journal file only has the journal header, no journal records. That case should have been cought earlier
+ /* Store/cache fc->eof_addr in local variable. It is possible the "repl_next" calls done below invoke "repl_read_file"
+ * which in turn invokes "update_eof_addr" and modify fc->eof_addr. But we limit our max_seqno search to
+ * the stored value of fc->eof_addr. Any changes to fc->eof_addr inside this function cause corresponding
+ * changes to ctl->max_seqno_eof_addr in subsequent calls to "update_max_seqno_info". Store copy of ctl->eof_eof_addr_final
+ * at the same time since ctl->eof_addr_final and ctl->eof_addr are maintained in sync.
+ */
+ max_seqno_eof_addr = fc->eof_addr;
+ eof_addr_final = ctl->eof_addr_final;
+ if (JNL_FILE_FIRST_RECORD == max_seqno_eof_addr)
+ { /* Journal file only has the journal header, no journal records. That case should have been caught earlier
* when the journal file was first open.
*/
assert(FALSE);
@@ -552,8 +580,9 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
}
QWASSIGN(reg_seqno, csa->hdr->reg_seqno);
QWDECRBYDW(reg_seqno, 1);
- assert(!ctl->max_seqno_final || ctl->eof_addr_final);
- if (QWGE(ctl->max_seqno, reg_seqno) || (ctl->max_seqno_final && ctl->first_read_done))
+ assert(!ctl->max_seqno_final || eof_addr_final);
+ if ((ctl->max_seqno >= reg_seqno) || (ctl->max_seqno_eof_addr == max_seqno_eof_addr)
+ || (ctl->max_seqno_final && ctl->first_read_done))
{ /* have searched already */
REPL_DPRINT4("UPDATE MAX SEQNO INFO : not reading file %s; max_seqno = "INT8_FMT", reg_seqno = "INT8_FMT"\n",
ctl->jnl_fn, INT8_PRINT(ctl->max_seqno), INT8_PRINT(reg_seqno));
@@ -561,10 +590,10 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
}
rb->buffindex = REPL_SCRATCHBUFF; /* temporarily set to scratch buffer */
b = &rb->buff[rb->buffindex];
- dskread = ROUND_DOWN(fc->eof_addr, REPL_BLKSIZE(rb));
- if (dskread == fc->eof_addr)
+ dskread = ROUND_DOWN(max_seqno_eof_addr, REPL_BLKSIZE(rb));
+ if (dskread == max_seqno_eof_addr)
dskread -= REPL_BLKSIZE(rb);
- QWASSIGN(max_seqno, seq_num_zero);
+ max_seqno = 0;
max_seqno_addr = 0;
max_seqno_found = FALSE;
do
@@ -577,9 +606,9 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
if (JNL_FILE_FIRST_RECORD == b->readaddr && SS_NORMAL != adjust_buff_leaving_hdr(rb))
{
assert(repl_errno == EREPL_BUFFNOTFRESH);
- GTMASSERT; /* Program bug */
+ assertpro(FALSE); /* Program bug */
}
- stop_at = dskread + MIN(REPL_BLKSIZE(rb), fc->eof_addr - dskread); /* Limit search to this block */
+ stop_at = dskread + MIN(REPL_BLKSIZE(rb), max_seqno_eof_addr - dskread); /* Limit search to this block */
/* If we don't limit the search, we may end up re-reading blocks that follow this block. The consequence of
* limiting the search is that we may not find the maximum close to the current state, but some time in the past
* for a file that is growing. We can live with that as we will redo the max search if necessary */
@@ -591,7 +620,7 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
rectype = (enum jnl_record_type)((jrec_prefix *)b->recbuff)->jrec_type;
if (IS_REPLICATED(rectype))
{
- QWASSIGN(max_seqno, GET_JNL_SEQNO(b->recbuff));
+ max_seqno = GET_JNL_SEQNO(b->recbuff);
max_seqno_addr = b->recaddr;
} else if (JRT_EOF == rectype)
break;
@@ -614,8 +643,8 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
{
assert(FALSE);
gtm_fork_n_core();
- rts_error(VARLSTCNT(6) ERR_JNLRECINCMPL, 4, b->recaddr, ctl->jnl_fn_len,
- ctl->jnl_fn, &ctl->seqno);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_JNLRECINCMPL, 4,
+ b->recaddr, ctl->jnl_fn_len, ctl->jnl_fn, &ctl->seqno);
}
break;
}
@@ -631,10 +660,9 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
}
} else
{
- if (EREPL_JNLRECFMT == status)
- rts_error(VARLSTCNT(5) ERR_JNLBADRECFMT, 3, ctl->jnl_fn_len, ctl->jnl_fn, b->recaddr);
- else
- GTMASSERT;
+ assertpro(EREPL_JNLRECFMT == status);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_JNLBADRECFMT, 3,
+ ctl->jnl_fn_len, ctl->jnl_fn, b->recaddr);
}
}
if ((max_seqno_found = (0 != max_seqno)) || (0 == dskread))
@@ -644,11 +672,17 @@ static int update_max_seqno_info(repl_ctl_element *ctl)
} while (TRUE);
rb->buffindex = REPL_MAINBUFF; /* reset back to the main buffer */
if (max_seqno_found)
- {
- QWASSIGN(ctl->max_seqno, max_seqno);
- ctl->max_seqno_dskaddr = max_seqno_addr;
- if (ctl->eof_addr_final)
+ { /* Assert that there is some progress in this call to "update_max_seqno_info" compared to the previous call */
+ assert((max_seqno_eof_addr > ctl->max_seqno_eof_addr) || (max_seqno_addr > ctl->max_seqno_dskaddr)
+ || (max_seqno > ctl->max_seqno));
+ CTL_SET_MAX_SEQNO(ctl, max_seqno, max_seqno_addr, max_seqno_eof_addr, DO_EOF_ADDR_CHECK);
+ if (eof_addr_final)
+ { /* Do not use ctl->eof_addr_final in the check above since it could have changed inside this function.
+ * We want to set all max_seqno* fields based on fc->eof_addr after update_eof_addr
+ * done at beginning of this function. This keeps all of them in sync with each other.
+ */
ctl->max_seqno_final = TRUE; /* No more max_seqno updates as this journal file has switched */
+ }
return (SS_NORMAL);
}
/* Two possibilities to get here :
@@ -708,9 +742,11 @@ static int first_read(repl_ctl_element *ctl)
if (adjust_buff_leaving_hdr(rb) != SS_NORMAL)
{
assert(repl_errno == EREPL_BUFFNOTFRESH);
- GTMASSERT; /* Program bug */
+ assertpro(FALSE); /* Program bug */
}
min_seqno_found = FALSE;
+ /* Since this is first time we are reading from this journal file, initialize fields cared for in CTL_SET_MAX_SEQNO macro */
+ DEBUG_ONLY(ctl->max_seqno = ctl->max_seqno_dskaddr = ctl->max_seqno_eof_addr = 0;)
while (!min_seqno_found)
{
if ((status = repl_next(rb)) == SS_NORMAL)
@@ -718,11 +754,14 @@ static int first_read(repl_ctl_element *ctl)
rectype = (enum jnl_record_type)((jrec_prefix *)b->recbuff)->jrec_type;
if (IS_REPLICATED(rectype))
{
- QWASSIGN(ctl->min_seqno, GET_JNL_SEQNO(b->recbuff));
- QWASSIGN(ctl->seqno, ctl->min_seqno);
+ ctl->min_seqno = GET_JNL_SEQNO(b->recbuff);
+ ctl->min_seqno_dskaddr = b->recaddr;
+ ctl->seqno = ctl->min_seqno;
ctl->tn = ((jrec_prefix *)b->recbuff)->tn;
- QWASSIGN(ctl->max_seqno, ctl->min_seqno);
- ctl->min_seqno_dskaddr = ctl->max_seqno_dskaddr = b->recaddr;
+ /* Since update_eof_addr has not yet been called (will be done as part of "update_max_seqno_info"
+ * at the end of this function), skip the fc->eof_addr check inside the below macro.
+ */
+ CTL_SET_MAX_SEQNO(ctl, ctl->min_seqno, b->recaddr, b->recaddr, SKIP_EOF_ADDR_CHECK);
ctl->file_state = JNL_FILE_OPEN;
min_seqno_found = TRUE;
} else if (rectype == JRT_EOF)
@@ -740,7 +779,8 @@ static int first_read(repl_ctl_element *ctl)
} else
{
if (status == EREPL_JNLRECFMT)
- rts_error(VARLSTCNT(5) ERR_JNLBADRECFMT, 3, ctl->jnl_fn_len, ctl->jnl_fn, b->recaddr);
+ rts_error_csa(CSA_ARG(&FILE_INFO(ctl->reg)->s_addrs) VARLSTCNT(5)
+ ERR_JNLBADRECFMT, 3, ctl->jnl_fn_len, ctl->jnl_fn, b->recaddr);
}
}
REPL_DPRINT5("FIRST READ of %s - Min seqno "INT8_FMT" min_seqno_dskaddr %u EOF addr %u\n",
@@ -748,7 +788,7 @@ static int first_read(repl_ctl_element *ctl)
if (update_max_seqno_info(ctl) != SS_NORMAL)
{
assert(repl_errno == EREPL_JNLEARLYEOF);
- GTMASSERT; /* Program bug */
+ assertpro(FALSE); /* Program bug */
}
REPL_DPRINT5("FIRST READ of %s - Max seqno "INT8_FMT" max_seqno_dskaddr %u EOF addr %d\n",
ctl->jnl_fn, INT8_PRINT(ctl->max_seqno), ctl->max_seqno_dskaddr, ctl->repl_buff->fc->eof_addr);
@@ -758,19 +798,20 @@ static int first_read(repl_ctl_element *ctl)
static void increase_buffer(unsigned char **buff, int *buflen, int buffer_needed)
{
- int newbuffsize, alloc_status;
+ int alloc_status, expandsize, newbuffsize;
unsigned char *old_msgp;
/* The tr size is not known apriori. Hence, a good guess of 1.5 times the current buffer space is used */
- newbuffsize = gtmsource_msgbufsiz + (gtmsource_msgbufsiz >> 1);
- if (buffer_needed > newbuffsize)
- newbuffsize = buffer_needed;
+ expandsize = (gtmsource_msgbufsiz >> 1);
+ if (expandsize < buffer_needed)
+ expandsize = buffer_needed;
+ newbuffsize = gtmsource_msgbufsiz + expandsize;
REPL_DPRINT3("Buff space shortage. Attempting to increase buff space. Curr buff space %d. Attempt increase to atleast %d\n",
gtmsource_msgbufsiz, newbuffsize);
old_msgp = (unsigned char *)gtmsource_msgp;
if ((alloc_status = gtmsource_alloc_msgbuff(newbuffsize, FALSE)) != SS_NORMAL)
{
- rts_error(VARLSTCNT(7) ERR_REPLCOMM, 0, ERR_TEXT, 2,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_REPLCOMM, 0, ERR_TEXT, 2,
LEN_AND_LIT("Error extending buffer space while reading files. Malloc error"), alloc_status);
}
REPL_DPRINT3("Old gtmsource_msgp = 0x%llx; New gtmsource_msgp = 0x%llx\n", (long long)old_msgp, (long long)gtmsource_msgp);
@@ -818,11 +859,8 @@ static int read_transaction(repl_ctl_element *ctl, unsigned char **buff, int *bu
assert(IS_REPLICATED(rectype));
rec_jnl_seqno = GET_REPL_JNL_SEQNO(b->recbuff);
assert(QWEQ(rec_jnl_seqno, ctl->seqno));
- if (QWGT(rec_jnl_seqno, ctl->max_seqno))
- {
- QWASSIGN(ctl->max_seqno, rec_jnl_seqno);
- ctl->max_seqno_dskaddr = b->recaddr;
- }
+ if (rec_jnl_seqno > ctl->max_seqno)
+ CTL_SET_MAX_SEQNO(ctl, rec_jnl_seqno, b->recaddr, b->recaddr, DO_EOF_ADDR_CHECK);
ctl->tn = ((jrec_prefix *)b->recbuff)->tn;
if (!IS_FENCED(rectype) || JRT_NULL == rectype)
{ /* Entire transaction done */
@@ -852,6 +890,7 @@ static int read_transaction(repl_ctl_element *ctl, unsigned char **buff, int *bu
*buff += b->reclen;
readlen += b->reclen;
assert(readlen % JNL_WRT_END_MODULUS == 0);
+ *bufsiz -= b->reclen;
} else
{
memcpy(tcombuffp, b->recbuff, b->reclen);
@@ -865,19 +904,15 @@ static int read_transaction(repl_ctl_element *ctl, unsigned char **buff, int *bu
if (num_tcom == 0) /* Read the whole trans */
trans_read = TRUE;
}
- *bufsiz -= b->reclen;
- QWASSIGN(rec_jnl_seqno, GET_JNL_SEQNO(b->recbuff));
- assert(QWEQ(rec_jnl_seqno, ctl->seqno));
- if (QWGT(rec_jnl_seqno, ctl->max_seqno))
- {
- QWASSIGN(ctl->max_seqno, rec_jnl_seqno);
- ctl->max_seqno_dskaddr = b->recaddr;
- }
+ rec_jnl_seqno = GET_JNL_SEQNO(b->recbuff);
+ assert(rec_jnl_seqno == ctl->seqno);
+ if (rec_jnl_seqno > ctl->max_seqno)
+ CTL_SET_MAX_SEQNO(ctl, rec_jnl_seqno, b->recaddr, b->recaddr, DO_EOF_ADDR_CHECK);
ctl->tn = ((jrec_prefix *)b->recbuff)->tn;
} else if (rectype == JRT_EOF)
{
assert(FALSE);
- rts_error(VARLSTCNT(7) ERR_REPLBRKNTRANS, 1, &read_jnl_seqno,
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_REPLBRKNTRANS, 1, &read_jnl_seqno,
ERR_TEXT, 2, LEN_AND_LIT("Early EOF found"));
}
} else if (status == EREPL_JNLRECINCMPL)
@@ -891,7 +926,8 @@ static int read_transaction(repl_ctl_element *ctl, unsigned char **buff, int *bu
{
assert(FALSE);
gtm_fork_n_core();
- rts_error(VARLSTCNT(6) ERR_JNLRECINCMPL, 4, b->recaddr, ctl->jnl_fn_len, ctl->jnl_fn, &ctl->seqno);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_JNLRECINCMPL, 4,
+ b->recaddr, ctl->jnl_fn_len, ctl->jnl_fn, &ctl->seqno);
}
gtmsource_poll_actions(TRUE);
SHORT_SLEEP(GTMSOURCE_WAIT_FOR_JNL_RECS);
@@ -905,10 +941,8 @@ static int read_transaction(repl_ctl_element *ctl, unsigned char **buff, int *bu
}
} else
{
- if (status == EREPL_JNLRECFMT)
- rts_error(VARLSTCNT(5) ERR_JNLBADRECFMT, 3, ctl->jnl_fn_len, ctl->jnl_fn, b->recaddr);
- else
- GTMASSERT;
+ assertpro(status == EREPL_JNLRECFMT);
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_JNLBADRECFMT, 3, ctl->jnl_fn_len, ctl->jnl_fn, b->recaddr);
}
}
/* Try positioning next read to the next seqno. Leave it as is if operation blocks (has to wait for records) */
@@ -943,11 +977,11 @@ static tr_search_state_t do_linear_search(repl_ctl_element *ctl, uint4 lo_addr,
if (b->readaddr == JNL_FILE_FIRST_RECORD && adjust_buff_leaving_hdr(rb) != SS_NORMAL)
{
assert(repl_errno == EREPL_BUFFNOTFRESH);
- GTMASSERT; /* Program bug */
+ assertpro(FALSE); /* Program bug */
}
REPL_DPRINT1("do_linear_search: initiating fresh read\n");
} else
- { /* use what has been read already */
+ { /* use what has been read already */
assert(read_seqno != ctl->seqno); /* if not, we'll skip to the next transaction and declare read_seqno not found */
}
found = TR_NOT_FOUND;
@@ -965,11 +999,8 @@ static tr_search_state_t do_linear_search(repl_ctl_element *ctl, uint4 lo_addr,
srch_status->prev_seqno = srch_status->seqno;
srch_status->seqno = rec_jnl_seqno;
}
- if (QWLT(ctl->max_seqno, rec_jnl_seqno))
- {
- QWASSIGN(ctl->max_seqno, rec_jnl_seqno);
- ctl->max_seqno_dskaddr = b->recaddr;
- }
+ if (ctl->max_seqno < rec_jnl_seqno)
+ CTL_SET_MAX_SEQNO(ctl, rec_jnl_seqno, b->recaddr, b->recaddr, DO_EOF_ADDR_CHECK);
QWASSIGN(ctl->seqno, rec_jnl_seqno);
ctl->tn = ((jrec_prefix *)b->recbuff)->tn;
if (QWEQ(rec_jnl_seqno, read_seqno))
@@ -981,7 +1012,8 @@ static tr_search_state_t do_linear_search(repl_ctl_element *ctl, uint4 lo_addr,
} else if (status == EREPL_JNLRECINCMPL)
found = TR_FIND_WOULD_BLOCK;
else if (status == EREPL_JNLRECFMT)
- rts_error(VARLSTCNT(5) ERR_JNLBADRECFMT, 3, ctl->jnl_fn_len, ctl->jnl_fn, b->recaddr);
+ rts_error_csa(CSA_ARG(&FILE_INFO(ctl->reg)->s_addrs) VARLSTCNT(5)
+ ERR_JNLBADRECFMT, 3, ctl->jnl_fn_len, ctl->jnl_fn, b->recaddr);
}
REPL_DPRINT2("do_linear_search: returning %s\n", (found == TR_NOT_FOUND) ? "TR_NOT_FOUND" :
(found == TR_FOUND) ? "TR_FOUND" :
@@ -1142,7 +1174,7 @@ static tr_search_state_t do_binary_search(repl_ctl_element *ctl, uint4 lo_addr,
break;
default: /* Why didn't we cover all cases? */
- GTMASSERT;
+ assertpro(FALSE);
} /* end switch */
if (!search_complete && low < high)
{
@@ -1357,19 +1389,22 @@ static int read_and_merge(unsigned char *buff, int maxbufflen, seq_num read_jnl_
if (TREF(gtm_environment_init)
DEBUG_ONLY(&& (WBTEST_CLOSE_JNLFILE != gtm_white_box_test_case_number)))
gtm_fork_n_core();
- rts_error(VARLSTCNT(4) ERR_SEQNUMSEARCHTIMEOUT, 2, &read_jnl_seqno, &read_jnl_seqno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SEQNUMSEARCHTIMEOUT, 2,
+ &read_jnl_seqno, &read_jnl_seqno);
}
}
}
read_len = read_regions(&buff, &buff_avail, pass > 1, &brkn_trans, read_jnl_seqno);
if (brkn_trans)
- rts_error(VARLSTCNT(3) ERR_REPLBRKNTRANS, 1, &read_jnl_seqno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_REPLBRKNTRANS, 1, &read_jnl_seqno);
total_read += read_len;
assert(total_read % JNL_WRT_END_MODULUS == 0);
}
if (tot_tcom_len > 0)
{ /* Copy all the TCOM records to the end of the buffer */
- assert(tot_tcom_len <= ((unsigned char *)gtmsource_msgp + gtmsource_msgbufsiz - buff));
+ if (tot_tcom_len > buff_avail)
+ increase_buffer(&buff, &buff_avail, tot_tcom_len);
+ assert(buff + tot_tcom_len <= ((unsigned char *)gtmsource_msgp + gtmsource_msgbufsiz));
memcpy(buff, gtmsource_tcombuff_start, tot_tcom_len);
total_read += tot_tcom_len;
assert(total_read % JNL_WRT_END_MODULUS == 0);
@@ -1411,9 +1446,9 @@ static int read_regions(unsigned char **buff, int *buff_avail,
while (found == TR_NOT_FOUND)
{ /* Find the generation of the journal file which has read_jnl_seqno */
for ( ; ctl != NULL && ctl->reg == region &&
- ((ctl->file_state == JNL_FILE_CLOSED && QWGT(read_jnl_seqno, ctl->max_seqno))
- || (ctl->file_state == JNL_FILE_EMPTY
- && QWGE(read_jnl_seqno, ctl->repl_buff->fc->jfh->start_seqno)));
+ ((JNL_FILE_CLOSED == ctl->file_state) && (read_jnl_seqno > ctl->max_seqno)
+ || (JNL_FILE_EMPTY == ctl->file_state)
+ && (read_jnl_seqno >= ctl->repl_buff->fc->jfh->start_seqno));
prev_ctl = ctl, ctl = ctl->next)
;
if (ctl == NULL || ctl->reg != region)
@@ -1538,9 +1573,9 @@ static int read_regions(unsigned char **buff, int *buff_avail,
ctl->prev->jnl_fn, INT8_PRINT(ctl->prev->max_seqno));
REPL_DPRINT3(") and %s (min seqno "INT8_FMT, ctl->jnl_fn, INT8_PRINT(ctl->min_seqno));
REPL_DPRINT2(") found while looking for "INT8_FMT"\n", INT8_PRINT(read_jnl_seqno));
- assert(ctl->prev->file_state == JNL_FILE_CLOSED &&
- QWLT(ctl->prev->max_seqno, read_jnl_seqno) ||
- ctl->prev->file_state == JNL_FILE_EMPTY);
+ assert((JNL_FILE_CLOSED == ctl->prev->file_state)
+ && (ctl->prev->max_seqno < read_jnl_seqno)
+ || (JNL_FILE_EMPTY == ctl->prev->file_state));
found = TR_WILL_NOT_BE_FOUND;
continue;
}
@@ -1585,7 +1620,7 @@ static int read_regions(unsigned char **buff, int *buff_avail,
} else
{
assert((ctl->file_state == JNL_FILE_OPEN || read_jnl_seqno <= ctl->max_seqno)
- && ctl->min_seqno <= read_jnl_seqno);
+ && (ctl->min_seqno <= read_jnl_seqno));
if (ctl->lookback)
{
assert(QWLE(read_jnl_seqno, ctl->seqno));
@@ -1606,7 +1641,7 @@ static int read_regions(unsigned char **buff, int *buff_avail,
assert(cumul_read % JNL_WRT_END_MODULUS == 0);
}
found = TR_FOUND;
- } else if (QWLT(read_jnl_seqno, ctl->seqno))
+ } else if (read_jnl_seqno < ctl->seqno)
{ /* This region is not involved in transaction read_jnl_seqno */
found = TR_WILL_NOT_BE_FOUND;
} else /* QWGT(read_jnl_seqno, ctl->seqno) */
@@ -1622,9 +1657,9 @@ static int read_regions(unsigned char **buff, int *buff_avail,
if (update_max_seqno_info(ctl) != SS_NORMAL)
{
assert(repl_errno == EREPL_JNLEARLYEOF);
- GTMASSERT; /* Program bug */
+ assertpro(FALSE); /* Program bug */
}
- if (QWLE(read_jnl_seqno, ctl->max_seqno))
+ if (read_jnl_seqno <= ctl->max_seqno)
{ /* May be found in this journal file,
* attempt to position next read to read_jnl_seqno
*/
@@ -1639,8 +1674,8 @@ static int read_regions(unsigned char **buff, int *buff_avail,
{ /* May be found in this jnl file, attempt to position next read to read_jnl_seqno */
position_read(ctl, read_jnl_seqno);
} else
- { /* Program bug - ctl->seqno should never be greater than ctl->max_seqno */
- GTMASSERT;
+ { /* Program bug - ctl->seqno should never be greater than ctl->max_seqno */
+ assertpro(FALSE);
}
}
}
@@ -1657,15 +1692,14 @@ static int read_regions(unsigned char **buff, int *buff_avail,
int gtmsource_readfiles(unsigned char *buff, int *data_len, int maxbufflen, boolean_t read_multiple)
{
int4 read_size, read_state, first_tr_len, tot_tr_len, loopcnt;
- unsigned char seq_num_str[32], *seq_num_ptr; /* INT8_PRINT */
+ unsigned char *orig_msgp, seq_num_str[32], *seq_num_ptr; /* INT8_PRINT */
jnlpool_ctl_ptr_t jctl;
gtmsource_local_ptr_t gtmsource_local;
seq_num read_jnl_seqno, max_read_seqno;
qw_num read_addr;
uint4 jnlpool_size;
- static int4 max_tr_size = MAX_TR_BUFFSIZE; /* Will generally be less than initial gtmsource_msgbufsiz;
- * allows for space to accommodate the last transaction */
boolean_t file2pool;
+ unsigned int start_heartbeat;
jctl = jnlpool.jnlpool_ctl;
gtmsource_local = jnlpool.gtmsource_local;
@@ -1682,7 +1716,6 @@ int gtmsource_readfiles(unsigned char *buff, int *data_len, int maxbufflen, bool
DEBUG_ONLY(loopcnt = 0;)
do
{
- assert(buff == (unsigned char *)gtmsource_msgp + REPL_MSG_HDRLEN); /* else increasing buffer space will not work */
assert(maxbufflen == gtmsource_msgbufsiz - REPL_MSG_HDRLEN);
DEBUG_ONLY(loopcnt++);
file2pool = FALSE;
@@ -1697,10 +1730,10 @@ int gtmsource_readfiles(unsigned char *buff, int *data_len, int maxbufflen, bool
REPL_DPRINT1("REPL_HISTREC message first needs to be sent before any more seqnos can be sent across\n");
return 0;
}
+ start_heartbeat = heartbeat_counter;
read_addr = gtmsource_local->read_addr;
first_tr_len = read_size = read_and_merge(buff, maxbufflen, read_jnl_seqno++) + REPL_MSG_HDRLEN;
tot_tr_len = 0;
- max_tr_size = MAX(max_tr_size, read_size);
do
{
tot_tr_len += read_size;
@@ -1728,26 +1761,35 @@ int gtmsource_readfiles(unsigned char *buff, int *data_len, int maxbufflen, bool
REPL_DPRINT3("Readfiles : after sync with pool read_seqno: %llu read_addr: %llu\n",
read_jnl_seqno, read_addr);
}
+ /* If reading multiple transactions in one shot, make sure we stop the bunching if at least 8 seconds
+ * (a heartbeat period) has elapsed during the bunching. This way we send whatever we have now rather
+ * than accumulating transactions in our huge internal buffer and avoid risking the user perception
+ * of no-progress. In the worst case we could be unresponsive for 8 seconds (1 heartbeat period)
+ * with this approach.
+ */
+ read_multiple = read_multiple && (start_heartbeat == heartbeat_counter);
if (read_multiple)
- {
- if ((tot_tr_len < max_tr_size) && (read_jnl_seqno < max_read_seqno))
- { /* Limit the read by the buffer length, or until there is no more to be read. If not
- * limited by the buffer length, the buffer will keep growing due to logic that expands
- * the buffer when needed. Recompute buff and maxbufflen as buffer may have expanded
- * during read_and_merge
- */
- buff = (unsigned char *)gtmsource_msgp + tot_tr_len + REPL_MSG_HDRLEN;
- maxbufflen = gtmsource_msgbufsiz - tot_tr_len - REPL_MSG_HDRLEN;
+ { /* Ok to read multiple transactions. Limit the multiple reads until there is no more to be read
+ * OR total read size reaches a fixed value MAX_TR_BUFFSIZE. This strikes a fine balance between
+ * reducing the # of "send()" system calls done by the source server versus being responsive to
+ * the user (in case of shutdown requests). Time spent reading multiple transactions is where
+ * the source server is not responsive to outside requests and is hence better minimized.
+ */
+ /* Note: Recompute buff and maxbufflen below buffer may have expanded during read_and_merge */
+ buff = (unsigned char *)gtmsource_msgp + tot_tr_len + REPL_MSG_HDRLEN;
+ maxbufflen = gtmsource_msgbufsiz - tot_tr_len - REPL_MSG_HDRLEN;
+ if ((tot_tr_len < MAX_TR_BUFFSIZE) && (read_jnl_seqno < max_read_seqno))
+ {
+ assert(0 < maxbufflen);
read_size = read_and_merge(buff, maxbufflen, read_jnl_seqno++) + REPL_MSG_HDRLEN;
- max_tr_size = MAX(max_tr_size, read_size);
/* Don't use buff to assign type and len as buffer may have expanded.
* Use gtmsource_msgp instead */
((repl_msg_ptr_t)((unsigned char *)gtmsource_msgp + tot_tr_len))->type = REPL_TR_JNL_RECS;
- ((repl_msg_ptr_t)((unsigned char *)gtmsource_msgp + tot_tr_len))->len = read_size;
+ ((repl_msg_ptr_t)((unsigned char *)gtmsource_msgp + tot_tr_len))->len = read_size;
continue;
}
- REPL_DPRINT6("Readfiles : tot_tr_len %d max_tr_size %d read_jnl_seqno %llu max_read_seqno %llu "
- "gtmsource_msgbufsize : %d; stop multiple reads\n", tot_tr_len, max_tr_size,
+ REPL_DPRINT5("Readfiles : tot_tr_len %d read_jnl_seqno %llu max_read_seqno %llu "
+ "gtmsource_msgbufsize : %d; stop multiple reads\n", tot_tr_len,
read_jnl_seqno, max_read_seqno, gtmsource_msgbufsiz);
}
break;
@@ -1823,7 +1865,7 @@ static int scavenge_closed_jnl_files(seq_num ack_seqno)
if (update_max_seqno_info(ctl) != SS_NORMAL)
{
assert(repl_errno == EREPL_JNLEARLYEOF);
- GTMASSERT; /* Program bug */
+ assertpro(FALSE); /* Program bug */
}
break;
case JNL_FILE_UNREAD :
@@ -1900,7 +1942,8 @@ int gtmsource_update_zqgblmod_seqno_and_tn(seq_num resync_seqno)
break;
if (0 == open_prev_gener(&old_ctl, ctl, resync_seqno)) /* this automatically does a "first_read" */
{ /* Previous journal file link was NULL. Issue error. */
- rts_error(VARLSTCNT(4) ERR_NOPREVLINK, 2, ctl->jnl_fn_len, ctl->jnl_fn);
+ rts_error_csa(CSA_ARG(&FILE_INFO(ctl->reg)->s_addrs)
+ VARLSTCNT(4) ERR_NOPREVLINK, 2, ctl->jnl_fn_len, ctl->jnl_fn);
}
assert(old_ctl->next == ctl);
assert(ctl->prev == old_ctl);
diff --git a/sr_unix/gtmxc_types.h b/sr_unix/gtmxc_types.h
index 1941697..7bcbd83 100644
--- a/sr_unix/gtmxc_types.h
+++ b/sr_unix/gtmxc_types.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -35,6 +35,10 @@ typedef float gtm_float_t;
typedef double gtm_double_t;
typedef char gtm_char_t;
typedef int (*gtm_pointertofunc_t)();
+/* Structure for passing (non-NULL-terminated) character arrays whose length corresponds to the value of the
+ * 'length' field. Note that for output-only gtm_string_t * arguments the 'length' field is set to the
+ * preallocation size of the buffer pointed to by 'address', while the first character of the buffer is '\0'.
+ */
typedef struct
{
gtm_long_t length;
diff --git a/sr_unix/gv_trigger.c b/sr_unix/gv_trigger.c
index 3ad8457..ea58a16 100644
--- a/sr_unix/gv_trigger.c
+++ b/sr_unix/gv_trigger.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -196,6 +196,7 @@ LITREF mval literal_zero;
#define KEYSUB_S2POOL_IF_NEEDED(KEYSUB_MVAL, KEYSUB, THISSUB) \
{ \
unsigned char str_buff[MAX_ZWR_KEY_SZ], *str_end; \
+ mstr opstr; \
\
KEYSUB_MVAL = lvvalarray[KEYSUB]; \
if (NULL == KEYSUB_MVAL) \
@@ -205,7 +206,9 @@ LITREF mval literal_zero;
KEYSUB_MVAL->mvtype = 0; \
lvvalarray[KEYSUB] = KEYSUB_MVAL; \
THISSUB = keysub_start[KEYSUB]; \
- str_end = gvsub2str((unsigned char *)THISSUB, str_buff, FALSE); \
+ opstr.addr = (char *)str_buff; \
+ opstr.len = MAX_ZWR_KEY_SZ; \
+ str_end = gvsub2str((unsigned char *)THISSUB, &opstr, FALSE); \
KEYSUB_MVAL->str.addr = (char *)str_buff; \
KEYSUB_MVAL->str.len = INTCAST(str_end - str_buff); \
KEYSUB_MVAL->mvtype = MV_STR; \
diff --git a/sr_unix/gvcst_init_sysops.c b/sr_unix/gvcst_init_sysops.c
index 78a5e9e..8aea912 100644
--- a/sr_unix/gvcst_init_sysops.c
+++ b/sr_unix/gvcst_init_sysops.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,11 +16,11 @@
#include <sys/param.h>
#endif
#include <errno.h>
-#include <sys/un.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/time.h>
#include "gtm_ipc.h"
+#include "gtm_un.h"
#include "gtm_socket.h"
#include "gtm_fcntl.h"
#include "gtm_unistd.h"
@@ -484,6 +484,7 @@ int db_init(gd_region *reg)
char s[JNLBUFFUPDAPNDX_SIZE]; /* JNLBUFFUPDAPNDX_SIZE is defined in jnl.h */
char *syscall;
void *mmapaddr;
+ int secshrstat;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -561,6 +562,14 @@ int db_init(gd_region *reg)
if (bypassed_ftok)
SEND_MSG(VARLSTCNT(4) ERR_TEXT, 2,
LEN_AND_LIT("bypassed at database encryption initialization"));
+ /* Re-read now possibly stale file header and redo the above based on the new header info */
+ READ_DB_FILE_HEADER(reg, tsd); /* file already opened by dbfilopn() done from gvcst_init() */
+ DO_BADDBVER_CHK(reg, tsd); /* need to do BADDBVER check before de-referencing shmid and semid from
+ * file header as they could be at different offsets if the database is
+ * V4-format
+ */
+ reg->dyn.addr->is_encrypted = tsd->is_encrypted; /* override with the value in file header */
+ do_crypt_init = (tsd->is_encrypted && !IS_LKE_IMAGE);
} /* else encryption is turned off in the file header. Continue as-is. Any encryption initialization done
* before is discarded
*/
@@ -1213,10 +1222,11 @@ int db_init(gd_region *reg)
memcpy(db_ipcs.fn, reg->dyn.addr->fname, reg->dyn.addr->fname_len);
db_ipcs.fn[reg->dyn.addr->fname_len] = 0;
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa);
- if (0 != send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0))
+ secshrstat = send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0);
+ csa->read_only_fs = (EROFS == secshrstat);
+ if ((0 != secshrstat) && !csa->read_only_fs)
RTS_ERROR(VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg),
ERR_TEXT, 2, LEN_AND_LIT("gtmsecshr failed to update database file header"));
-
}
if (gtm_fullblockwrites)
{ /* We have been asked to do FULL BLOCK WRITES for this database. On *NIX, attempt to get the filesystem
diff --git a/sr_unix/heartbeat_timer.c b/sr_unix/heartbeat_timer.c
index 71127a1..696e967 100644
--- a/sr_unix/heartbeat_timer.c
+++ b/sr_unix/heartbeat_timer.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,164 +24,24 @@
#include "gtmio.h" /* for CLOSEFILE used by the F_CLOSE macro in JNL_FD_CLOSE */
#include "repl_sp.h" /* for F_CLOSE used by the JNL_FD_CLOSE macro */
#include "iosp.h" /* for SS_NORMAL used by the JNL_FD_CLOSE macro */
-
#include "heartbeat_timer.h"
#include "gt_timer.h"
#include "gtmimagename.h"
#include "dpgbldir.h"
#include "have_crit.h"
#include "anticipatory_freeze.h"
-
#ifdef DEBUG
-STATICDEF uint4 next_heartbeat_counter = 1; /* the heartbeat_counter at which enospc manipulations need to happen */
-GBLREF boolean_t is_jnlpool_creator; /* The purpose of this check is to assign only one process responsible of
- * setting fake ENOSPC flags. If we had multiple processes messing with FREEZE,
- * the test would freeze more often and eventually do nothing but freeze.
- */
-STATICDEF uint4 syslog_deferred = 0;
+#include "fake_enospc.h"
#endif
-GBLREF volatile uint4 heartbeat_counter;
GBLREF boolean_t is_src_server;
GBLREF enum gtmImageTypes image_type;
-GBLREF uint4 process_id;
+GBLREF int process_exiting;
GBLREF jnlpool_addrs jnlpool;
+GBLREF uint4 process_id;
+GBLREF volatile uint4 heartbeat_counter;
GBLREF volatile int4 gtmMallocDepth;
-#ifdef DEBUG
-
-#define ENOSPC_FROZEN_DURATION 2 /* 16 seconds */
-#define ENOSPC_UNFROZEN_DURATION (2 * (rand() % 120 + 1)) /* 16 seconds to 32 minutes */
-#define MAX_REGIONS 50
-
-#define NONE 0 /* 1/2 probablility */
-#define DB_ON 1 /* 1/6 probablility */
-#define JNL_ON 2 /* 1/6 probablility */
-#define DB_AND_JNL_ON 3 /* 1/6 probablility */
-#define MAX_ENOSPC_TARGET 4
-
-error_def(ERR_TEXT);
-error_def(ERR_FAKENOSPCLEARED);
-
-void choose_random_reg_list(char *enospc_enable_list, int n_reg)
-{
- int i;
-
- assert(MAX_REGIONS >= n_reg);
- for (i = 0; i < n_reg; i++)
- {
- if(rand() % 2) /* Should we trigger fake ENOSPC on this region */
- enospc_enable_list[i] = rand() % (MAX_ENOSPC_TARGET - 1) + 1; /* What kind? */
- else
- enospc_enable_list[i] = NONE;
- }
-}
-
-void set_enospc_if_needed()
-{
- gd_addr *addr_ptr;
- char enospc_enable_list[MAX_REGIONS];
- boolean_t ok_to_interrupt, is_time_to_act;
- DCL_THREADGBL_ACCESS;
-
- SETUP_THREADGBL_ACCESS;
-
- if (TREF(gtm_test_fake_enospc) && is_jnlpool_creator && ANTICIPATORY_FREEZE_AVAILABLE)
- {
- ok_to_interrupt = (INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) && (0 == gtmMallocDepth);
- is_time_to_act = (next_heartbeat_counter == heartbeat_counter);
- if (syslog_deferred && ok_to_interrupt)
- {
- send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_FAKENOSPCLEARED, 1, (heartbeat_counter - syslog_deferred));
- syslog_deferred = 0;
- }
- if (!is_time_to_act || syslog_deferred || (!ok_to_interrupt && !IS_REPL_INST_FROZEN))
- {
- /* We have to skip this because we have just fallen into deferred zone or we are currently in it */
- if (is_time_to_act)
- next_heartbeat_counter++; /* Try again in the next heartbeat */
- return;
- }
- assert(0 == syslog_deferred);
- srand(time(NULL));
- addr_ptr = get_next_gdr(NULL);
- if (NULL == addr_ptr) /* Ensure that there is a global directory to operate on. */
- return;
- assert(NULL == get_next_gdr(addr_ptr));
- /* Randomly simulate ENOSPC or free space. NO more than 50 regions are allowed to avoid unnecessary
- * malloc/frees in debug-only code
- */
- assert(MAX_REGIONS >= addr_ptr->n_regions);
- if (!IS_REPL_INST_FROZEN)
- { /* We are in an UNFROZEN state, and about to be FROZEN due to ENOSPC */
- choose_random_reg_list(enospc_enable_list, addr_ptr->n_regions);
- next_heartbeat_counter = heartbeat_counter + ENOSPC_FROZEN_DURATION;
- } else
- { /* We are in a FROZEN state, and about to be UNFROZEN due to free space */
- memset(enospc_enable_list, 0, MAX_REGIONS);
- next_heartbeat_counter = heartbeat_counter + ENOSPC_UNFROZEN_DURATION;
- if (!ok_to_interrupt)
- syslog_deferred = heartbeat_counter;
- }
- set_enospc_flags(addr_ptr, enospc_enable_list, ok_to_interrupt);
- }
-}
-
-void set_enospc_flags(gd_addr *addr_ptr, char enospc_enable_list[], boolean_t ok_to_interrupt)
-{
- gd_region *r_local, *r_top;
- int i;
- sgmnt_addrs *csa;
- const char *syslog_msg;
- DCL_THREADGBL_ACCESS;
-
- SETUP_THREADGBL_ACCESS;
-
- for (r_local = addr_ptr->regions, r_top = r_local + addr_ptr->n_regions, i = 0;
- r_local < r_top; r_local++, i++)
- {
- if ((dba_bg != r_local->dyn.addr->acc_meth) && (dba_mm != r_local->dyn.addr->acc_meth))
- continue;
- csa = REG2CSA(r_local);
- if ((NULL != csa) && (NULL != csa->nl) && INST_FREEZE_ON_NOSPC_ENABLED(csa))
- {
- syslog_msg = NULL;
- switch(enospc_enable_list[i])
- {
- case NONE:
- if (csa->nl->fake_db_enospc || csa->nl->fake_jnl_enospc)
- {
- syslog_msg = "Turning off fake ENOSPC for both database and journal file.";
- csa->nl->fake_db_enospc = FALSE;
- csa->nl->fake_jnl_enospc = FALSE;
- }
- break;
- case DB_ON:
- syslog_msg = "Turning on fake ENOSPC only for database file.";
- csa->nl->fake_db_enospc = TRUE;
- csa->nl->fake_jnl_enospc = FALSE;
- break;
- case JNL_ON:
- syslog_msg = "Turning on fake ENOSPC only for journal file.";
- csa->nl->fake_db_enospc = FALSE;
- csa->nl->fake_jnl_enospc = TRUE;
- break;
- case DB_AND_JNL_ON:
- syslog_msg = "Turning on fake ENOSPC for both database and journal file.";
- csa->nl->fake_db_enospc = TRUE;
- csa->nl->fake_jnl_enospc = TRUE;
- break;
- default:
- assert(FALSE);
- }
- if (ok_to_interrupt && (NULL != syslog_msg))
- send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_TEXT, 2, DB_LEN_STR(r_local), ERR_TEXT, 2,
- LEN_AND_STR(syslog_msg));
- }
- }
-}
-#endif
-
void heartbeat_timer(void)
{
gd_addr *addr_ptr;
@@ -195,7 +55,10 @@ void heartbeat_timer(void)
/* It will take heartbeat_counter about 1014 years to overflow. */
heartbeat_counter++;
- DEBUG_ONLY(set_enospc_if_needed());
+# ifdef DEBUG
+ if (!process_exiting)
+ fake_enospc();
+# endif
/* Check every 1 minute if we have an older generation journal file open. If so, close it.
* The only exceptions are
* a) The source server can have older generations open and they should not be closed.
@@ -205,7 +68,7 @@ void heartbeat_timer(void)
* the midst of a journal file switch is tricky so we check if the process is in
* crit for this region and if so we skip the close this time and wait for the next heartbeat.
*/
- if ((INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) && !is_src_server
+ if (((INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) && (!process_exiting)) && !is_src_server
&& (0 == heartbeat_counter % NUM_HEARTBEATS_FOR_OLDERJNL_CHECK))
{
for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr))
diff --git a/sr_unix/heartbeat_timer.h b/sr_unix/heartbeat_timer.h
index 0b0be3c..eddedf9 100644
--- a/sr_unix/heartbeat_timer.h
+++ b/sr_unix/heartbeat_timer.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,8 +19,6 @@
#define HEARTBEAT_INTERVAL (HEARTBEAT_INTERVAL_IN_SECS * MILLISECS_IN_SEC) /* ms */
#define NUM_HEARTBEATS_FOR_OLDERJNL_CHECK 8 /* gives a total of 8 * 8 = 64 seconds between checks of older jnl files */
-GBLREF boolean_t heartbeat_started;
-
/* The heartbeat timer is used
* 1) To periodically check if we have older generation journal files open and if so to close them.
* 2) By mutex logic to approximately measure the time spent sleeping while waiting for CRIT or MSEMLOCK.
@@ -28,6 +26,8 @@ GBLREF boolean_t heartbeat_started;
*/
#define START_HEARTBEAT_IF_NEEDED \
{ \
+ GBLREF boolean_t heartbeat_started; \
+ \
if (!heartbeat_started) \
{ \
start_timer((TID)&heartbeat_timer, HEARTBEAT_INTERVAL, heartbeat_timer, 0, NULL); \
@@ -38,12 +38,3 @@ GBLREF boolean_t heartbeat_started;
void heartbeat_timer(void);
#endif
-
-#ifdef DEBUG
-#include "gdsroot.h"
-#include "gdsbt.h"
-#include "gdsfhead.h"
-void set_enospc_if_needed(void);
-void choose_random_reg_list(char *enospc_enable_list, int);
-void set_enospc_flags(gd_addr *addr_ptr, char enospc_enable_list[], boolean_t ok_to_interrupt);
-#endif
diff --git a/sr_unix/incr_link.c b/sr_unix/incr_link.c
index e6a03f4..f20e4ee 100644
--- a/sr_unix/incr_link.c
+++ b/sr_unix/incr_link.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,10 +11,15 @@
#include "mdef.h"
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+
#include <errno.h>
#include "gtm_string.h"
#include "gtm_unistd.h"
#include "gtm_stdio.h"
+#include "gtm_stat.h"
#include <rtnhdr.h>
#include "compiler.h"
@@ -31,12 +36,23 @@
#include "gtmdbglvl.h"
#include "cmd_qlf.h" /* needed for CQ_UTF8 */
#include "gtm_text_alloc.h"
+#include "zhist.h"
+#include "send_msg.h"
+#include "cacheflush.h"
+
+/* Define linkage types */
+typedef enum
+{
+ LINK_SHRLIB = 1, /* 0001 Link routine from a shared library */
+ LINK_SHROBJ, /* 0002 Link routine from a shared object */
+ LINK_PPRIVOBJ /* 0003 Link a process-private object */
+} linktype;
#define RELOCATE(field, type, base) field = (type)((unsigned char *)(field) + (UINTPTR_T)(base))
-#define RELREAD 50 /* number of relocation entries to buffer */
+#define RELREAD 50 /* number of relocation entries to buffer */
/* This macro will check if the file is an old non-shared-binary variant of GT.M code and if
- * so just return false to signal a recompile. The assumption is that if we fall out of this
+ * so just return IL_RECOMPILE to signal a recompile. The assumption is that if we fall out of this
* macro that there is truly a problem and other measures should be taken (e.g. call zlerror()).
* At some point this code can be disabled with the NO_NONUSB_RECOMPILE varible defined. Rather
* than keep old versions of control blocks around that will confuse the issue, we know that the
@@ -44,7 +60,7 @@
* bytes from that location and check against the JSB_MARKER we still use today.
*/
#ifndef NO_NONUSB_RECOMPILE
-# define CHECK_NONUSB_RECOMPILE \
+# define CHECK_NONUSB_RECOMPILE_RETURN \
{ \
if (-1 != (status = (ssize_t)lseek(file_desc, COFFHDRLEN, SEEK_SET))) \
{ \
@@ -54,33 +70,37 @@
if ((0 == status) && (0 == MEMCMP_LIT(marker, JSB_MARKER))) \
{ \
free(hdr); \
- return FALSE; /* Signal recompile */ \
+ hdr = NULL; \
+ return IL_RECOMPILE; /* Signal recompile */ \
} \
}
#else
-# define CHECK_NONUSB_RECOMPILE /* No old recompile check is being generated */
+# define CHECK_NONUSB_RECOMPILE_RETURN /* No old recompile check is being generated */
#endif
-/* INCR_LINK - read and process a mumps object module. Link said module to currently executing image */
-
-LITREF char gtm_release_name[];
-LITREF int4 gtm_release_name_len;
-
+/* At some point these statics (like all the others) need to move into gtm_threadgbl since these values should
+ * *not* be shared amongst the threads of the future.
+ */
static unsigned char *sect_ro_rel, *sect_rw_rel, *sect_rw_nonrel;
-static boolean_t shlib;
static rhdtyp *hdr;
GBLREF mident_fixed zlink_mname;
GBLREF mach_inst jsb_action[JSB_ACTION_N_INS];
GBLREF uint4 gtmDebugLevel;
GBLREF boolean_t gtm_utf8_mode;
-
-ZOS_ONLY(
+#ifdef __MVS__
GBLDEF unsigned char *text_section;
GBLDEF boolean_t extended_symbols_present;
+/* If ZOS is ever revived, verify the following two fields used properly. For example, total_length is declared here and
+ * passed to extract_text where it is instead called text_counter_ptr. The name "total_length" is also overloaded with
+ * a local of the same name in $sr_os390/obj_filesp.c.
+ */
GBLDEF int total_length;
-GBLDEF int text_counter = 0;
-)
+GBLDEF int text_counter;
+#endif
+
+LITREF char gtm_release_name[];
+LITREF int4 gtm_release_name_len;
typedef struct res_list_struct
{
@@ -93,141 +113,189 @@ typedef struct res_list_struct
error_def(ERR_DLLCHSETM);
error_def(ERR_DLLCHSETUTF8);
error_def(ERR_DLLVERSION);
-error_def(ERR_INVOBJ);
+error_def(ERR_INVOBJFILE);
error_def(ERR_LOADRUNNING);
error_def(ERR_TEXT);
+error_def(ERR_SYSCALL);
+error_def(ERR_ZLINKFILE);
-void res_free(res_list *root);
-boolean_t addr_fix(int file, unsigned char *shdr, urx_rtnref *urx_lcl);
-void zl_error(int4 file, zro_ent *zroe, int4 err, int4 len, char *addr, int4 len2, char *addr2);
-void zl_error_hskpng(int4 file);
-int cacheflush (void *addr, long nbytes, int cache_select);
+STATICFNDCL void res_free(res_list *root);
+STATICFNDCL boolean_t addr_fix(int file, unsigned char *shdr, linktype linktyp, urx_rtnref *urx_lcl);
+STATICFNDCL void zl_error(linktype linktyp, int4 file, int4 err, int4 len, char *addr, int4 len2, char *addr2);
+STATICFNDCL void zl_error_hskpng(linktype linktyp, int4 file);
-bool incr_link (int file_desc, zro_ent *zro_entry)
+/* incr_link - read and process a mumps object module. Link said module to currently executing image */
+boolean_t incr_link (int file_desc, zro_ent *zro_entry, uint4 fname_len, char *fname)
{
rhdtyp *old_rhead;
- int sect_ro_rel_size, sect_rw_rel_size;
- ssize_t status, sect_rw_nonrel_size;
+ int sect_ro_rel_size, sect_rw_rel_size, name_buf_len, alloc_len, order, rc, save_errno;
+ uint4 lcl_compiler_qlf;
+ boolean_t dynlits;
+ ssize_t status, sect_rw_nonrel_size, sect_ro_rel_offset;
+ size_t offset_correction;
lab_tabent *lbt_ent, *lbt_bot, *lbt_top, *olbt_ent, *olbt_bot, *olbt_top;
mident_fixed module_name;
pre_v5_mident *pre_v5_routine_name;
urx_rtnref urx_lcl_anchor;
- int order;
- boolean_t dynlits;
- size_t offset_correction;
- unsigned char *shdr, *rel_base;
+ unsigned char *shdr, *rel_base, *newaddr;
mval *curlit, *littop;
lab_tabent *curlbe, *lbetop;
var_tabent *curvar, *vartop;
- char name_buf[PATH_MAX+1];
- int name_buf_len, alloc_len;
- char marker[SIZEOF(JSB_MARKER) - 1];
- char *rw_rel_start;
+ char name_buf[PATH_MAX + 1], marker[SIZEOF(JSB_MARKER) - 1], *rw_rel_start;
+ linktype linktyp;
+ struct stat obj_stat;
+ ZOS_ONLY(ESD symbol;)
+# ifdef _AIX
+ FILHDR hddr;
+ unsigned short magic;
+# endif
+ DCL_THREADGBL_ACCESS;
- AIX_ONLY(
- FILHDR hddr;
- unsigned short magic;
- )
- ZOS_ONLY(
- ESD symbol;
- total_length = 0;
- extended_symbols_present = FALSE;
- text_counter = 0;
- memset(&symbol, 0 , SIZEOF(ESD));
- assert(NULL == text_section);
- ZOS_FREE_TEXT_SECTION;
- )
+ SETUP_THREADGBL_ACCESS;
+# ifdef __MVS__
+ total_length = 0;
+ extended_symbols_present = FALSE;
+ text_counter = 0;
+ memset(&symbol, 0 , SIZEOF(ESD));
+ assert(NULL == text_section);
+ ZOS_FREE_TEXT_SECTION;
+# endif
urx_lcl_anchor.len = 0;
urx_lcl_anchor.addr = 0;
urx_lcl_anchor.lab = 0;
urx_lcl_anchor.next = 0;
- shlib = FALSE;
+ assert(NULL == hdr);
+ assert(NULL == sect_ro_rel);
+ assert(NULL == sect_rw_rel);
+ assert(NULL == sect_rw_nonrel);
hdr = NULL;
shdr = NULL;
sect_ro_rel = sect_rw_rel = sect_rw_nonrel = NULL;
if (file_desc)
- { /* This is a disk resident object we will be reading in */
- shlib = FALSE;
- assert(NULL == zro_entry);
+ { /* This is a disk resident object we mmap and share if autorelink is enabled in that directory, or instead we
+ * read/link into process private storage if autorelink is not enabled.
+ */
+ if ((NULL == zro_entry) || (NULL == zro_entry->relinkctl_sgmaddr))
+ linktyp = LINK_PPRIVOBJ;
+ else
+ linktyp = LINK_SHROBJ;
+ NON_USHBIN_ONLY(assert(LINK_PPRIVOBJ == linktyp)); /* No autorelink in non-ushbin platform */
} else
- {
- shlib = TRUE;
- assert(zro_entry);
+ { /* With no file descriptor, this can only be linkage from a shared library */
+ linktyp = LINK_SHRLIB;
+ NON_USHBIN_ONLY(assert(FALSE /* Shared libraries not supported on this platform */));
}
/* Get the routine header where we can make use of it */
hdr = (rhdtyp *)malloc(SIZEOF(rhdtyp));
- if (shlib)
- { /* Make writable copy of header as header of record.
- * On some platforms, the address returned by dlsym() is not the actual shared code address, but normally
- * an address to the linkage table, eg. TOC (AIX), PLT (HP-UX). Computing the actual shared code address
- * is platform dependent and is handled by the macro (see incr_link_sp.h)
- */
- shdr = (unsigned char *)GET_RTNHDR_ADDR(zro_entry->shrsym);
- memcpy(hdr, shdr, SIZEOF(rhdtyp));
- hdr->shlib_handle = zro_entry->shrlib;
- } else
- { /* Seek past native object headers to get GT.M object's routine header */
- /* To check if it is not an xcoff64 bit .o */
- AIX_ONLY(
+ switch(linktyp)
+ {
+# ifdef USHBIN_SUPPORTED
+ case LINK_SHRLIB:
+ /* Copy routine header to process private storage so we can make changes to it. Note that on
+ * some platforms, the address returned by dlsym() is not the actual shared code address, but
+ * normally an address to the linkage table, eg. TOC (AIX), PLT (HP-UX). Computing the actual
+ * shared code address is platform dependent and is handled by the macro (see incr_link_sp.h).
+ */
+ shdr = (unsigned char *)GET_RTNHDR_ADDR(zro_entry->shrsym);
+ memcpy(hdr, shdr, SIZEOF(rhdtyp));
+ hdr->shlib_handle = zro_entry->shrlib;
+ break;
+ case LINK_SHROBJ:
+ FSTAT_FILE(file_desc, &obj_stat, rc);
+ if (-1 == rc)
+ { /* Need to not use zl_error() here since need compound error to put out errno */
+ save_errno = errno;
+ ZOS_FREE_TEXT_SECTION;
+ zl_error_hskpng(linktyp, file_desc);
+ rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, fname_len, fname, save_errno);
+ }
+ /* Share the object file (in its entirety) via mmap() */
+ shdr = (unsigned char *)mmap(NULL, obj_stat.st_size, PROT_EXEC|PROT_READ, MAP_SHARED, file_desc, 0)
+ + NATIVE_HDR_LEN; /* shdr->routinehdr (past native object header) */
+ if (MAP_FAILED == (void *)shdr)
+ { /* If mmap() fails, send error to both process and to syslog. Note we do not use zlerror()
+ * here since need to send a compound message about the failure.
+ */
+ save_errno = errno;
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(12) ERR_ZLINKFILE, 2, fname_len, fname, ERR_SYSCALL,
+ 5, LEN_AND_LIT("mmap"), CALLFROM, save_errno);
+ ZOS_FREE_TEXT_SECTION;
+ zl_error_hskpng(linktyp, file_desc);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(12) ERR_ZLINKFILE, 2, fname_len, fname, ERR_SYSCALL,
+ 5, LEN_AND_LIT("mmap"), CALLFROM, save_errno);
+ }
+ memcpy(hdr, shdr, SIZEOF(rhdtyp));
+ hdr->shared_len = obj_stat.st_size; /* Record length we shared so we can unmap it when done */
+ break;
+# endif
+ case LINK_PPRIVOBJ:
+ /* Seek past native object headers to get GT.M object's routine header */
+ /* To check if it is not an xcoff64 bit .o */
+# ifdef _AIX
DOREADRC(file_desc, &hddr, SIZEOF(FILHDR), status);
if (0 == status)
{
magic = hddr.f_magic;
- if (-1 == (status = (ssize_t)lseek(file_desc, -(SIZEOF(FILHDR)), SEEK_SET)))
- status = errno;
if (magic != U64_TOCMAGIC)
- return FALSE;
+ {
+ ZOS_FREE_TEXT_SECTION;
+ zl_error_hskpng(linktyp, file_desc);
+ return IL_RECOMPILE;
+ }
} else
- zl_error(file_desc, zro_entry, ERR_INVOBJ, 0, 0, 0, 0);
- )
- /* In the GOFF .o on zOS, if the symbol name(name of the module) exceeds ESD_NAME_MAX_LENGTH (8), *
- * then 2 extra extended records are emitted, which causes the start of text section to vary
- */
-#ifdef __MVS__
+ zl_error(linktyp, file_desc, ERR_INVOBJFILE, fname_len, fname, 0, NULL);
+# endif
+ /* In the GOFF .o on zOS, if the symbol name(name of the module) exceeds ESD_NAME_MAX_LENGTH (8),
+ * then 2 extra extended records are emitted, which causes the start of text section to vary
+ */
+# ifdef __MVS__
DOREADRC(file_desc, &symbol, SIZEOF(symbol), status); /* This is HDR record */
if (0 == status)
{
DOREADRC(file_desc, &symbol, SIZEOF(symbol), status) /* First symbol (ESD record) */
- if (0 == status)
- {
- if (0x01 == symbol.ptv[1]) /* which means the extended records are there */
- extended_symbols_present = TRUE;
- else
+ if (0 == status)
{
- assert(0x0 == symbol.ptv[1]);
- extended_symbols_present = FALSE;
+ if (0x01 == symbol.ptv[1]) /* Means the extended records are there */
+ extended_symbols_present = TRUE;
+ else
+ {
+ assert(0x0 == symbol.ptv[1]);
+ extended_symbols_present = FALSE;
+ }
}
- }
}
if (0 != status)
- zl_error(file_desc, zro_entry, ERR_INVOBJ, 0, 0, 0, 0);
-#endif
- if (-1 != (status = (ssize_t)lseek(file_desc, NATIVE_HDR_LEN, SEEK_SET)))
- {
- ZOS_ONLY(extract_text(file_desc, &total_length);)
- DOREADRC_OBJFILE(file_desc, hdr, SIZEOF(rhdtyp), status);
- } else
- status = errno;
- if (0 != status)
- {
- CHECK_NONUSB_RECOMPILE;
- zl_error(file_desc, zro_entry, ERR_INVOBJ, 0, 0, 0, 0);
- }
+ zl_error(linktyp, file_desc, ERR_INVOBJFILE, fname_len, fname, 0, NULL);
+# endif
+ if (-1 != (status = (ssize_t)lseek(file_desc, NATIVE_HDR_LEN, SEEK_SET)))
+ {
+ ZOS_ONLY(extract_text(file_desc, &total_length));
+ DOREADRC_OBJFILE(file_desc, hdr, SIZEOF(rhdtyp), status);
+ } else
+ status = errno;
+ if (0 != status)
+ {
+ CHECK_NONUSB_RECOMPILE_RETURN;
+ zl_error(linktyp, file_desc, ERR_INVOBJFILE, fname_len, fname, 0, NULL);
+ }
+ break;
+ default:
+ assertpro(FALSE /* Invalid linkage type for this platform*/);
}
if ((0 != memcmp(hdr->jsb, (char *)jsb_action, SIZEOF(jsb_action)))
- || (0 != memcmp(&hdr->jsb[SIZEOF(jsb_action)], JSB_MARKER,
- MIN(STR_LIT_LEN(JSB_MARKER), SIZEOF(hdr->jsb) - SIZEOF(jsb_action)))))
+ || (0 != memcmp(&hdr->jsb[SIZEOF(jsb_action)], JSB_MARKER,
+ MIN(STR_LIT_LEN(JSB_MARKER), SIZEOF(hdr->jsb) - SIZEOF(jsb_action)))))
{
- if (!shlib) /* Shared library cannot recompile so this is always an error */
+ if (LINK_SHRLIB != linktyp) /* Shared library cannot recompile so this is always an error */
{
- CHECK_NONUSB_RECOMPILE;
+ CHECK_NONUSB_RECOMPILE_RETURN;
}
- zl_error(file_desc, zro_entry, ERR_INVOBJ, 0, 0, 0, 0);
+ zl_error(linktyp, file_desc, ERR_INVOBJFILE, fname_len, fname, 0, NULL);
}
/* Binary version check. If no match, shlib gets error, otherwise signal recompile */
if (MAGIC_COOKIE != hdr->objlabel)
{
- if (shlib)
+ if (LINK_SHRLIB == linktyp)
{
if (MAGIC_COOKIE_V5 > hdr->objlabel)
{ /* The library was built using a version prior to V50FT01. The routine_name field of the
@@ -237,59 +305,60 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
pre_v5_routine_name = (pre_v5_mident *)((char*)hdr + PRE_V5_RTNHDR_RTNOFF);
for (len = 0; len < SIZEOF(pre_v5_mident) && pre_v5_routine_name->c[len]; len++)
;
- zl_error(0, zro_entry, ERR_DLLVERSION, len, &(pre_v5_routine_name->c[0]),
- zro_entry->str.len, zro_entry->str.addr);
+ zl_error(linktyp, 0, ERR_DLLVERSION, len, &(pre_v5_routine_name->c[0]),
+ zro_entry->str.len, zro_entry->str.addr);
}
-#if defined(__osf__) || defined(__hppa)
+# if defined(__osf__) || defined(__hppa)
else if (MAGIC_COOKIE_V52 > hdr->objlabel)
{ /* Note: routine_name field has not been relocated yet, so compute its absolute
* address in the shared library and use it
*/
v50v51_mstr *mstr5051; /* declare here so don't have to conditionally add above */
mstr5051 = (v50v51_mstr *)((char *)hdr + V50V51_RTNHDR_RTNMSTR_OFFSET);
- zl_error(0, zro_entry, ERR_DLLVERSION, mstr5051->len,
+ zl_error(linktyp, 0, ERR_DLLVERSION, mstr5051->len,
((char *)shdr + *(int4 *)((char *)hdr + V50V51_FTNHDR_LITBASE_OFFSET)
- + (int4)mstr5051->addr),
- zro_entry->str.len, zro_entry->str.addr);
+ + (int4)mstr5051->addr), zro_entry->str.len, zro_entry->str.addr);
}
-#endif
+# endif
else /* V52 or later but not current version */
{ /* Note: routine_name field has not been relocated yet, so compute its absolute
* address in the shared library and use it
*/
- zl_error(0, zro_entry, ERR_DLLVERSION, hdr->routine_name.len, (char *)shdr +
- (UINTPTR_T)hdr->literal_text_adr + (UINTPTR_T)hdr->routine_name.addr,
- zro_entry->str.len, zro_entry->str.addr);
+ zl_error(linktyp, 0, ERR_DLLVERSION, hdr->routine_name.len, (char *)shdr +
+ (UINTPTR_T)hdr->literal_text_adr + (UINTPTR_T)hdr->routine_name.addr,
+ zro_entry->str.len, zro_entry->str.addr);
}
}
ZOS_FREE_TEXT_SECTION;
- return FALSE;
+ zl_error_hskpng(linktyp, file_desc);
+ return IL_RECOMPILE;
}
if (((hdr->compiler_qlf & CQ_UTF8) && !gtm_utf8_mode) || (!(hdr->compiler_qlf & CQ_UTF8) && gtm_utf8_mode))
- { /* object file compiled with a different $ZCHSET is being used */
- if (shlib) /* Shared library cannot recompile so this is always an error */
+ { /* Object file compiled with a different $ZCHSET is being used */
+ lcl_compiler_qlf = hdr->compiler_qlf; /* Will be cleaned up soon so save a copy */
+ if (LINK_SHRLIB == linktyp) /* Shared library cannot recompile so this is always an error */
{ /* Note: routine_name field has not been relocated yet, so compute its absolute address
* in the shared library and use it
*/
- if ((hdr->compiler_qlf & CQ_UTF8) && !gtm_utf8_mode)
+ if ((lcl_compiler_qlf & CQ_UTF8) && !gtm_utf8_mode)
{
- zl_error(0, zro_entry, ERR_DLLCHSETUTF8, (int)hdr->routine_name.len, (char *)shdr +
- (UINTPTR_T)hdr->literal_text_adr + (UINTPTR_T)hdr->routine_name.addr,
+ zl_error(linktyp, 0, ERR_DLLCHSETUTF8, (int)hdr->routine_name.len, (char *)shdr +
+ (UINTPTR_T)hdr->literal_text_adr + (UINTPTR_T)hdr->routine_name.addr,
(int)zro_entry->str.len, zro_entry->str.addr);
} else
{
- zl_error(0, zro_entry, ERR_DLLCHSETM, (int)hdr->routine_name.len, (char *)shdr +
+ zl_error(linktyp, 0, ERR_DLLCHSETM, (int)hdr->routine_name.len, (char *)shdr +
(UINTPTR_T)hdr->literal_text_adr + (UINTPTR_T)hdr->routine_name.addr,
(int)zro_entry->str.len, zro_entry->str.addr);
}
}
- zl_error_hskpng(file_desc);
- if ((hdr->compiler_qlf & CQ_UTF8) && !gtm_utf8_mode)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_INVOBJ, 0,
- ERR_TEXT, 2, LEN_AND_LIT("Object compiled with CHSET=UTF-8 which is different from $ZCHSET"));
+ zl_error_hskpng(linktyp, file_desc);
+ if ((lcl_compiler_qlf & CQ_UTF8) && !gtm_utf8_mode)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_INVOBJFILE, 2, fname_len, fname, ERR_TEXT, 2,
+ LEN_AND_LIT("Object compiled with CHSET=UTF-8 which is different from $ZCHSET"));
else
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_INVOBJ, 0,
- ERR_TEXT, 2, LEN_AND_LIT("Object compiled with CHSET=M which is different from $ZCHSET"));
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_INVOBJFILE, 2, fname_len, fname, ERR_TEXT, 2,
+ LEN_AND_LIT("Object compiled with CHSET=M which is different from $ZCHSET"));
}
/* Read in and/or relocate the pointers to the various sections. To understand the size calculations
* being done note that the contents of the various xxx_adr pointers in the routine header are
@@ -300,44 +369,63 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
*/
dynlits = DYNAMIC_LITERALS_ENABLED(hdr);
rw_rel_start = RW_REL_START_ADR(hdr); /* Marks end of R/O-release section and start of R/W-release section */
- if (shlib)
- rel_base = shdr;
- else
+ switch(linktyp)
{
- sect_ro_rel_size = (unsigned int)((INTPTR_T)rw_rel_start - (INTPTR_T)hdr->ptext_adr);
- sect_ro_rel = GTM_TEXT_ALLOC(sect_ro_rel_size);
- /* It should be aligned well at this point but make a debug level check to verify */
- assert((INTPTR_T)sect_ro_rel == ((INTPTR_T)sect_ro_rel & ~(LINKAGE_PSECT_BOUNDARY - 1)));
- DOREADRC_OBJFILE(file_desc, sect_ro_rel, sect_ro_rel_size, status);
- if (0 != status)
- zl_error(file_desc, zro_entry, ERR_INVOBJ, 0, 0, 0, 0);
- /* The offset correction is the amount that needs to be applied to a given storage area that
- * is no longer contiguous with the routine header. In this case, the code and other sections
- * are no longer contiguous with the routine header but the initial offsets in the routine
- * header make the assumption that they are. Therefore these sections have a base address equal
- * to the length of the routine header. The offset correction is what will adjust the base
- * address so that this offset is removed and the pointer can now truly point to the section
- * it needs to point to.
- *
- * An example may make this more clear. We have two blocks of storage: block A and block B. Now
- * block A has 2 fields that will ultimately point into various places in block B. These pointers
- * are initialized to be the offset from the start of block A to the position in block B. Now we
- * have two cases. In the first case block A and block B are contiguous. Therefore in order to
- * relocate the addresses in block A, all you have to do is add the base address of block A to
- * those addresses and they then properly address the areas in block B. Case 2 is that block A
- * and block B are not contiguous. In this case, to properly adjust the addresses in block A, we
- * need to do two things. Obviously we need the address for block B. But the offsets currently in
- * the addresses in block A assume that block A is the origin, not block B so the length of block A
- * must be subtracted from the offsets to provide the true offset into block B. Then we can add the
- * address of the block B to this address and have now have the addesses in block A properly address
- * the areas in block B. In this case, block A is the routine header, block B is the read-only
- * releasable section. Case one is when the input is from a shared library, case 2 when from a file.
- */
- offset_correction = (size_t)hdr->ptext_adr;
- rel_base = sect_ro_rel - offset_correction;
+ case LINK_SHROBJ:
+ case LINK_SHRLIB:
+ rel_base = shdr;
+ break;
+ case LINK_PPRIVOBJ:
+ sect_ro_rel_size = (unsigned int)((INTPTR_T)rw_rel_start - (INTPTR_T)hdr->ptext_adr);
+ sect_ro_rel = GTM_TEXT_ALLOC(sect_ro_rel_size);
+ /* R/O-release section should be aligned well at this point but make a debug level check to verify */
+ assert((INTPTR_T)sect_ro_rel == ((INTPTR_T)sect_ro_rel & ~(LINKAGE_PSECT_BOUNDARY - 1)));
+ DOREADRC_OBJFILE(file_desc, sect_ro_rel, sect_ro_rel_size, status);
+ if (0 != status)
+ zl_error(linktyp, file_desc, ERR_INVOBJFILE, fname_len, fname, 0, NULL);
+ /* The offset correction is the amount that needs to be applied to a given storage area that
+ * is no longer contiguous with the routine header. In this case, the code and other sections
+ * are no longer contiguous with the routine header but the initial offsets in the routine
+ * header make the assumption that they are. Therefore these sections have a base address equal
+ * to the length of the routine header. The offset correction is what will adjust the base
+ * address so that this offset is removed and the pointer can now truly point to the section
+ * it needs to point to.
+ *
+ * An example may make this more clear. We have two blocks of storage: block A and block B. Now
+ * block A has 2 fields that will ultimately point into various places in block B. These pointers
+ * are initialized to be the offset from the start of block A to the position in block B. Now we
+ * have two cases. In the first case block A and block B are contiguous. Therefore in order to
+ * relocate the addresses in block A, all you have to do is add the base address of block A to
+ * those addresses and they then properly address the areas in block B. Case 2 is that block A
+ * and block B are not contiguous. In this case, to properly adjust the addresses in block A, we
+ * need to do two things. Obviously we need the address for block B. But the offsets currently in
+ * the addresses in block A assume that block A is the origin, not block B so the length of block A
+ * must be subtracted from the offsets to provide the true offset into block B. Then we can add the
+ * address of the block B to this address and have now have the addesses in block A properly address
+ * the areas in block B. In this case, block A is the routine header, block B is the read-only
+ * releasable section. Case one is when the input is from a shared library, case 2 when from a file.
+ */
+ offset_correction = (size_t)hdr->ptext_adr;
+ rel_base = sect_ro_rel - offset_correction;
+ break;
+ default:
+ assert(FALSE /* Invalid link type */);
}
RELOCATE(hdr->ptext_adr, unsigned char *, rel_base);
RELOCATE(hdr->ptext_end_adr, unsigned char *, rel_base);
+ /* Initialize hdr->shared_ptext_adr appropriately for the link type */
+ switch(linktyp)
+ {
+ case LINK_SHROBJ:
+ case LINK_SHRLIB:
+ hdr->shared_ptext_adr = hdr->ptext_adr;
+ break;
+ case LINK_PPRIVOBJ:
+ hdr->shared_ptext_adr = NULL;
+ break;
+ default:
+ assert(FALSE /* Invalid link type */);
+ }
RELOCATE(hdr->lnrtab_adr, lnr_tabent *, rel_base);
RELOCATE(hdr->literal_text_adr, unsigned char *, rel_base);
if (dynlits)
@@ -345,13 +433,19 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
/* Read-write releasable section */
sect_rw_rel_size = (int)((INTPTR_T)hdr->labtab_adr - (INTPTR_T)rw_rel_start);
sect_rw_rel = malloc(sect_rw_rel_size);
- if (shlib)
- memcpy(sect_rw_rel, shdr + (INTPTR_T)rw_rel_start, sect_rw_rel_size);
- else
+ switch(linktyp)
{
- DOREADRC_OBJFILE(file_desc, sect_rw_rel, sect_rw_rel_size, status);
- if (0 != status)
- zl_error(file_desc, zro_entry, ERR_INVOBJ, 0, 0, 0, 0);
+ case LINK_SHROBJ:
+ case LINK_SHRLIB:
+ memcpy(sect_rw_rel, shdr + (INTPTR_T)rw_rel_start, sect_rw_rel_size);
+ break;
+ case LINK_PPRIVOBJ:
+ DOREADRC_OBJFILE(file_desc, sect_rw_rel, sect_rw_rel_size, status);
+ if (0 != status)
+ zl_error(linktyp, file_desc, ERR_INVOBJFILE, fname_len, fname, 0, NULL);
+ break;
+ default:
+ assert(FALSE /* Invalid link type */);
}
offset_correction = (size_t)rw_rel_start;
rel_base = sect_rw_rel - offset_correction;
@@ -385,10 +479,20 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
RELOCATE(curvar->var_name.addr, char *, hdr->literal_text_adr);
}
/* Fixup header's source path and routine names as they both point to the offsets from the
- * beginning of the literal text pool
+ * beginning of the literal text pool.
*/
hdr->src_full_name.addr += (INTPTR_T)hdr->literal_text_adr;
hdr->routine_name.addr += (INTPTR_T)hdr->literal_text_adr;
+ if (LINK_SHROBJ == linktyp)
+ { /* For values in shared objects (but not shared libraries) put the name and
+ * path in malloc'd space so in a core file we can have access to the names.
+ */
+ newaddr = malloc(hdr->src_full_name.len + hdr->routine_name.len);
+ memcpy(newaddr, hdr->src_full_name.addr, hdr->src_full_name.len);
+ memcpy(newaddr + hdr->src_full_name.len, hdr->routine_name.addr, hdr->routine_name.len);
+ hdr->src_full_name.addr = (char *)newaddr;
+ hdr->routine_name.addr = (char *)(newaddr + hdr->src_full_name.len);
+ }
if (GDL_PrintEntryPoints & gtmDebugLevel)
{ /* Prepare name and address for announcement.. */
name_buf_len = (PATH_MAX > hdr->src_full_name.len) ? hdr->src_full_name.len : PATH_MAX;
@@ -399,13 +503,19 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
/* Read-write non-releasable section */
sect_rw_nonrel_size = hdr->labtab_len * SIZEOF(lab_tabent);
sect_rw_nonrel = malloc(sect_rw_nonrel_size);
- if (shlib)
- memcpy(sect_rw_nonrel, shdr + (INTPTR_T)hdr->labtab_adr, sect_rw_nonrel_size);
- else
+ switch(linktyp)
{
- DOREADRC_OBJFILE(file_desc, sect_rw_nonrel, sect_rw_nonrel_size, status);
- if (0 != status)
- zl_error(file_desc, zro_entry, ERR_INVOBJ, 0, 0, 0, 0);
+ case LINK_SHROBJ:
+ case LINK_SHRLIB:
+ memcpy(sect_rw_nonrel, shdr + (INTPTR_T)hdr->labtab_adr, sect_rw_nonrel_size);
+ break;
+ case LINK_PPRIVOBJ:
+ DOREADRC_OBJFILE(file_desc, sect_rw_nonrel, sect_rw_nonrel_size, status);
+ if (0 != status)
+ zl_error(linktyp, file_desc, ERR_INVOBJFILE, fname_len, fname, 0, NULL);
+ break;
+ default:
+ assert(FALSE /* Invalid link type */);
}
hdr->labtab_adr = (lab_tabent *)sect_rw_nonrel;
/* Relocations for read-write non-releasable section. Perform relocation on label table entries. */
@@ -415,18 +525,19 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
RELOCATE(curlbe->lnr_adr, lnr_tabent *, hdr->lnrtab_adr);
}
/* Remaining initialization */
+ hdr->zhist = TREF(recent_zhist); /* TODO: Document what this is or change to different mechanism */
hdr->current_rhead_adr = hdr;
assert(hdr->routine_name.len < SIZEOF(zlink_mname.c));
memcpy(&zlink_mname.c[0], hdr->routine_name.addr, hdr->routine_name.len);
zlink_mname.c[hdr->routine_name.len] = 0;
/* Do address fix up with relocation and symbol entries from the object. Note that shdr will
- * never be dereferenced except under a test of the shlib static flag to indicate we are processing
- * a shared library.
+ * never be dereferenced except under a test of the linktyp flag to indicate we are processing
+ * a shared library or a shared object.
*/
- if (!addr_fix(file_desc, shdr, &urx_lcl_anchor))
+ if (!addr_fix(file_desc, shdr, linktyp, &urx_lcl_anchor))
{
urx_free(&urx_lcl_anchor);
- zl_error(file_desc, zro_entry, ERR_INVOBJ, 0, 0, 0, 0);
+ zl_error(linktyp, file_desc, ERR_INVOBJFILE, fname_len, fname, 0, NULL);
}
/* Register new routine in routine name vector displacing old one and performing any necessary cleanup */
if (!zlput_rname(hdr))
@@ -434,7 +545,7 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
urx_free(&urx_lcl_anchor);
/* Copy routine name to local variable because zl_error frees it. */
memcpy(&module_name.c[0], hdr->routine_name.addr, hdr->routine_name.len);
- zl_error(file_desc, zro_entry, ERR_LOADRUNNING, (int)hdr->routine_name.len, &module_name.c[0], 0, 0);
+ zl_error(linktyp, file_desc, ERR_LOADRUNNING, (int)hdr->routine_name.len, &module_name.c[0], 0, NULL);
}
/* Fix up of routine headers for old versions of routine so they point to the newest version */
old_rhead = hdr->old_rhead_adr;
@@ -450,7 +561,7 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
for (; lbt_ent < lbt_top; lbt_ent++)
{
MIDENT_CMP(&olbt_ent->lab_name, &lbt_ent->lab_name, order);
- if (order <= 0)
+ if (0 >= order)
break;
}
if ((lbt_ent < lbt_top) && !order)
@@ -478,19 +589,33 @@ bool incr_link (int file_desc, zro_ent *zro_entry)
old_rhead->literal_adr = hdr->literal_adr;
old_rhead->literal_text_adr = hdr->literal_text_adr;
old_rhead->literal_len = hdr->literal_len;
+ old_rhead->zhist = hdr->zhist;
old_rhead = (rhdtyp *)old_rhead->old_rhead_adr;
}
/* Add local unresolves to global chain freeing elements that already existed in the global chain */
urx_add(&urx_lcl_anchor);
/* Resolve all unresolved entries in the global chain that reference this routine */
urx_resolve(hdr, (lab_tabent *)lbt_bot, (lab_tabent *)lbt_top);
- if (!shlib)
+ if (LINK_PPRIVOBJ == linktyp)
cacheflush(hdr->ptext_adr, (hdr->ptext_end_adr - hdr->ptext_adr), BCACHE);
ZOS_FREE_TEXT_SECTION;
- return TRUE;
+ /* Don't leave global pointers around to active blocks */
+ hdr = NULL;
+ shdr = NULL;
+ sect_ro_rel = sect_rw_rel = sect_rw_nonrel = NULL;
+ return IL_DONE;
}
-boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
+/* Routine to do address relocations/fixups for the M routine being linked as well as resolve those addresses that
+ * can be resolved and create a chain of the external routine/label references that remain unresolved.
+ *
+ * Parameters:
+ * file - file descriptor of open file.
+ * shdr - address of shared header for shared object and shared library linked objects.
+ * linktyp - type of linkage performed (enum linktype).
+ * urx_lcl - address of urx_lcl structure to put our references in temporarily.
+ */
+STATICFNDEF boolean_t addr_fix(int file, unsigned char *shdr, linktype linktyp, urx_rtnref *urx_lcl)
{
res_list *res_root, *new_res, *res_temp, *res_temp1;
unsigned char *symbols, *sym_temp, *sym_temp1, *symtop, *res_addr;
@@ -509,22 +634,29 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
numrel = (int)((hdr->sym_table_off - hdr->rel_table_off) / SIZEOF(struct relocation_info));
if ((numrel * SIZEOF(struct relocation_info)) != (hdr->sym_table_off - hdr->rel_table_off))
return FALSE; /* Size was not even multiple of relocation entries */
- while (numrel > 0)
+ while (0 < numrel)
{
- if (shlib)
- { /* All relocation entries already available */
- rel_read = numrel;
- rel_ptr = (struct relocation_info *)((char *)shdr + hdr->rel_table_off);
- } else
- { /* Buffer the relocation entries */
- rel_read = (numrel < RELREAD ? numrel : RELREAD);
- DOREADRC_OBJFILE(file, &rel[0], rel_read * SIZEOF(struct relocation_info), status);
- if (0 != status)
- {
- res_free(res_root);
- return FALSE;
- }
- rel_ptr = &rel[0];
+ switch(linktyp)
+ {
+ case LINK_SHROBJ:
+ case LINK_SHRLIB:
+ /* All relocation entries already available */
+ rel_read = numrel;
+ rel_ptr = (struct relocation_info *)((char *)shdr + hdr->rel_table_off);
+ break;
+ case LINK_PPRIVOBJ:
+ /* Buffer the relocation entries */
+ rel_read = (numrel < RELREAD ? numrel : RELREAD);
+ DOREADRC_OBJFILE(file, &rel[0], rel_read * SIZEOF(struct relocation_info), status);
+ if (0 != status)
+ {
+ res_free(res_root);
+ return FALSE;
+ }
+ rel_ptr = &rel[0];
+ break;
+ default:
+ assert(FALSE /* Invalid link type */);
}
numrel -= rel_read;
for (; rel_read; --rel_read, ++rel_ptr)
@@ -532,7 +664,7 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
new_res = (res_list *)malloc(SIZEOF(*new_res));
new_res->symnum = rel_ptr->r_symbolnum;
new_res->addr = rel_ptr->r_address;
- new_res->next = new_res->list = 0;
+ new_res->next = new_res->list = NULL;
/* Insert the relocation entry in symbol number order on the unresolved chain */
if (!res_root)
res_root = new_res;
@@ -569,28 +701,33 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
if (!res_root)
return TRUE; /* No unresolved symbols .. we have been successful */
/* Read in the symbol table text area. First word is length of following section */
- if (shlib)
+ switch(linktyp)
{
- memcpy(&string_size, shdr + hdr->sym_table_off, SIZEOF(string_size));
- symbols = shdr + hdr->sym_table_off + SIZEOF(string_size);
- string_size -= SIZEOF(string_size);
- } else
- {
- DOREADRC_OBJFILE(file, &string_size, SIZEOF(string_size), status);
- if (0 != status)
- {
- res_free(res_root);
- return FALSE;
- }
- string_size -= SIZEOF(string_size);
- symbols = malloc(string_size);
- DOREADRC_OBJFILE(file, symbols, string_size, status);
- if (0 != status)
- {
- free(symbols);
- res_free(res_root);
- return FALSE;
- }
+ case LINK_SHROBJ:
+ case LINK_SHRLIB:
+ memcpy(&string_size, shdr + hdr->sym_table_off, SIZEOF(string_size));
+ symbols = shdr + hdr->sym_table_off + SIZEOF(string_size);
+ string_size -= SIZEOF(string_size);
+ break;
+ case LINK_PPRIVOBJ:
+ DOREADRC_OBJFILE(file, &string_size, SIZEOF(string_size), status);
+ if (0 != status)
+ {
+ res_free(res_root);
+ return FALSE;
+ }
+ string_size -= SIZEOF(string_size);
+ symbols = malloc(string_size);
+ DOREADRC_OBJFILE(file, symbols, string_size, status);
+ if (0 != status)
+ {
+ free(symbols);
+ res_free(res_root);
+ return FALSE;
+ }
+ break;
+ default:
+ assert(FALSE /* Invalid link type */);
}
/* Match up unresolved entries with the null terminated symbol name entries from the
* symbol text pool we just read in.
@@ -607,7 +744,7 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
{ /* Find end of *this* symbol we are bypassing */
if (sym_temp >= symtop)
{
- if (!shlib)
+ if (LINK_PPRIVOBJ == linktyp)
free(symbols);
res_free(res_root);
return FALSE;
@@ -622,7 +759,7 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
{
if (sym_temp1 >= symtop)
{
- if (!shlib)
+ if (LINK_PPRIVOBJ == linktyp)
free(symbols);
res_free(res_root);
return FALSE;
@@ -648,7 +785,7 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
{
if (sym_temp1 >= symtop)
{
- if (!shlib)
+ if (LINK_PPRIVOBJ == linktyp)
free(symbols);
res_free(res_root);
return FALSE;
@@ -667,16 +804,16 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
if (rtn)
{ /* The routine part at least is known */
if (!labsym)
- res_addr = (unsigned char *)rtn; /* resolve to routine header */
+ res_addr = (unsigned char *)rtn; /* Resolve to routine header */
else
{ /* Look our target label up in the routines label table */
label = rtn->labtab_adr;
labtop = label + rtn->labtab_len;
for (; label < labtop && ((sym_size != label->lab_name.len) ||
- memcmp(&labid.c[0], label->lab_name.addr, sym_size)); label++)
+ memcmp(&labid.c[0], label->lab_name.addr, sym_size)); label++)
;
if (label < labtop)
- res_addr = (unsigned char *)&label->lnr_adr; /* resolve to label entry address */
+ res_addr = (unsigned char *)&label->lnr_adr; /* Resolve to label entry address */
else
res_addr = NULL; /* Label not found .. potential future problem. For now
* just leave it unresolved */
@@ -700,7 +837,7 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
urx_rp = urx_putrtn(rtn_str.addr, (int)rtn_str.len, urx_lcl); /* Find/create unresolved node for routine */
res_temp = res_root->next;
while(res_root)
- { /* add unresolved addr entry to existing or new routine and/or label node. */
+ { /* Add unresolved addr entry to existing or new routine and/or label node. */
if (labsym)
urx_putlab(&labid.c[0], sym_size, urx_rp, (char *)hdr->linkage_adr + res_root->addr);
else
@@ -716,15 +853,18 @@ boolean_t addr_fix (int file, unsigned char *shdr, urx_rtnref *urx_lcl)
}
res_root = res_temp;
}
- if (!shlib)
+ if (LINK_PPRIVOBJ == linktyp)
free(symbols);
return TRUE;
}
/* Release the resolution chain .. Called as part of an error since normal processing will
* have already released all elements on this chain.
+ *
+ * Parameter:
+ * root - anchor for system resolution chain
*/
-void res_free (res_list *root)
+STATICFNDEF void res_free(res_list *root)
{
res_list *temp;
@@ -742,36 +882,58 @@ void res_free (res_list *root)
}
}
-/* ZL_ERROR - perform cleanup and signal errors found in zlinking a mumps object module */
-void zl_error (int4 file, zro_ent *zroe, int4 err, int4 len, char *addr, int4 len2, char *addr2)
+/* Routine to perform cleanup and signal errors found in zlinking a mumps object module.
+ *
+ * Parameters:
+ * linktyp - type of linkage performed (enum linktype).
+ * file - file descriptor of open file.
+ * err - error code of error to raise.
+ * len/addr - length/address of 1st substitution string.
+ * len2/addr2 - length/address of 2nd substitution string.
+ */
+STATICFNDEF void zl_error(linktype linktyp, int4 file, int4 err, int4 len, char *addr, int4 len2, char *addr2)
{
+ int rc;
+
ZOS_FREE_TEXT_SECTION;
- zl_error_hskpng(file);
- /* 0, 2, or 4 arguments */
- if (0 == len)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) err);
+ zl_error_hskpng(linktyp, file);
+ if (LINK_PPRIVOBJ == linktyp)
+ { /* Only private process links have this area to free */
+ CLOSEFILE_RESET(file, rc); /* resets "file" to FD_INVALID */
+ }
+ /* 5 or 7 arguments */
+ if (0 == len2)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) err, 2, len, addr);
else
- if (0 == len2)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) err, 2, len, addr);
- else
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) err, 4, len, addr, len2, addr2);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) err, 4, len, addr, len2, addr2);
}
-/* ZL_ERROR-housekeeping */
-void zl_error_hskpng(int4 file)
+/* Routine to perform basic housekeeping for zl_error() but allowed to be called separately by other errors.
+ *
+ * Parameters:
+ * linktyp - type of linkage performed (enum linktype).
+ * file - file descriptor of open file.
+ */
+STATICFNDEF void zl_error_hskpng(linktype linktyp, int4 file)
{
- int rc;
-
- if (!shlib)
- { /* Only non shared library links have these areas to free */
- if (hdr)
- free(hdr);
- if (sect_ro_rel)
- GTM_TEXT_FREE(sect_ro_rel);
- if (sect_rw_rel)
- free(sect_rw_rel);
- if (sect_rw_nonrel)
- free(sect_rw_nonrel);
- CLOSEFILE_RESET(file, rc); /* resets "file" to FD_INVALID */
+ if (NULL != hdr)
+ {
+ free(hdr);
+ hdr = NULL;
+ }
+ if (NULL != sect_rw_rel)
+ {
+ free(sect_rw_rel);
+ sect_rw_rel = NULL;
+ }
+ if (NULL != sect_rw_nonrel)
+ {
+ free(sect_rw_nonrel);
+ sect_rw_nonrel = NULL;
+ }
+ if ((LINK_PPRIVOBJ == linktyp) && (NULL != sect_ro_rel))
+ { /* Only private process links have this area to free */
+ GTM_TEXT_FREE(sect_ro_rel);
+ sect_ro_rel = NULL;
}
}
diff --git a/sr_unix/incr_link.h b/sr_unix/incr_link.h
index 1ad00b2..e78a59a 100644
--- a/sr_unix/incr_link.h
+++ b/sr_unix/incr_link.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,12 +12,15 @@
#ifndef INCR_LINK_INCLUDED
#define INCR_LINK_INCLUDED
+#define IL_DONE 1 /* calling convention descended from VMS */
+#define IL_RECOMPILE 0
+
#ifdef USHBIN_SUPPORTED
#include <incr_link_sp.h>
-bool incr_link(int file_desc, zro_ent *zro_entry);
#else
-bool incr_link(int file_desc);
+#include "zroutinessp.h" /* need zro_ent typedef for i386 dummy argument */
#endif
+boolean_t incr_link(int file_desc, zro_ent *zro_entry, uint4 fname_len, char *fname);
#ifdef __MVS__
#define ZOS_FREE_TEXT_SECTION \
diff --git a/sr_unix/io_open_try.c b/sr_unix/io_open_try.c
index c1697d5..cce8cb3 100644
--- a/sr_unix/io_open_try.c
+++ b/sr_unix/io_open_try.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,9 +33,7 @@
#include "iottdef.h"
#include "iomtdef.h"
#include "io_dev_dispatch.h"
-#ifdef __MVS__
#include "iormdef.h"
-#endif
#include "eintr_wrappers.h"
#include "mmemory.h"
#include "gtm_caseconv.h"
@@ -95,9 +93,9 @@ bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mva
int p_offset, len;
boolean_t mknod_err , stat_err, dir_err;
- int save_mknod_err, save_stat_err;
+ int save_mknod_err, save_stat_err, save_gsn_err;
- int sockstat, sockoptval;
+ int gso_stat, gsn_stat, sockoptval;
in_port_t sockport;
GTM_SOCKLEN_TYPE socknamelen;
struct sockaddr_storage sockname;
@@ -253,27 +251,32 @@ bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mva
tl->iod->type = rm;
break;
case S_IFSOCK:
- /* If SOCK_STREAM, AF_INET, and not [kr]shell port assume we were
- started by inetd.
- We are not able to trigger exception until active_device set
- and exception parsed which is not done for fd == 0/1 which
- is from io_init called from gtm_startup before condition handlers
- are setup so we can't report errors, just will be treated as rm.
- Note the fall through if the above conditions are not true to
- maintain compatibility for rshd startup PER 3252.
- 28-JUL-1995 14:24:31 FERTIG REPLACE IO_OPEN_TRY.C(18)
- "PER 3252: fix problems starting up mumps from an ""rsh"" or ""remsh"""
- */
+ /* If SOCK_STREAM, AF_INET/AF_INET6, and not [kr]shell port assume we were
+ * started by inetd.
+ * We are not able to trigger exception until active_device set
+ * and exception parsed which is not done for fd == 0/1 which
+ * is from io_init called from gtm_startup before condition handlers
+ * are setup so we can't report errors, just will be treated as rm.
+ * Note the fall through if the above conditions are not true to
+ * maintain compatibility for rshd startup PER 3252.
+ * 28-JUL-1995 14:24:31 FERTIG REPLACE IO_OPEN_TRY.C(18)
+ * "PER 3252: fix problems starting up mumps from an ""rsh"" or ""remsh"""
+ *
+ * Different UNIX flavors behave differently when given an AF_UNIX socket,
+ * some errors and some setting sa_family to zero, so recognize each platform
+ * behavior and assume a local socket for those cases.
+ */
sockoptlen = SIZEOF(sockoptval);
- sockstat = getsockopt(file_des, SOL_SOCKET, SO_TYPE, &sockoptval,
+ gso_stat = getsockopt(file_des, SOL_SOCKET, SO_TYPE, &sockoptval,
(GTM_SOCKLEN_TYPE *)&sockoptlen);
- if (!sockstat && SOCK_STREAM == sockoptval)
+ if (!gso_stat && SOCK_STREAM == sockoptval)
{
socknamelen = SIZEOF(sockname);
- sockstat = getsockname(file_des,
+ gsn_stat = getsockname(file_des,
(struct sockaddr *)&sockname,
(GTM_SOCKLEN_TYPE *)&socknamelen);
- if (!sockstat && ((AF_INET == ((sockaddr_ptr)&sockname)->sa_family)
+ save_gsn_err = errno;
+ if (!gsn_stat && ((AF_INET == ((sockaddr_ptr)&sockname)->sa_family)
|| (AF_INET6 == ((sockaddr_ptr)&sockname)->sa_family)))
{
port_len = NI_MAXSERV;
@@ -292,12 +295,33 @@ bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mva
break;
}
}
+ else if ((!gsn_stat && ((AF_UNIX == ((sockaddr_ptr)&sockname)->sa_family)
+ || (0 == socknamelen)
+ || (0 == ((sockaddr_ptr)&sockname)->sa_family)))
+ || (EOPNOTSUPP == save_gsn_err)
+# if defined(_AIX)
+ || (ENOTCONN == save_gsn_err)
+# endif
+# if defined(__sun) || defined(__hpux)
+ || (EINVAL == save_gsn_err)
+# endif
+ )
+ {
+ tl->iod->type = gtmsocket;
+ break;
+ }
}
+ /* We don't expect any unusual socket types (e.g. SOCK_DGRAM) in testing,
+ * so assert instead of falling through in DEBUG.
+ */
+ assert(NULL == "Unknown socket type");
/* fall through */
case 0:
+ assert(NULL == "Zero file type");
tl->iod->type = ff;
break;
default:
+ assert(NULL == "Unknown value for (outbuf.st_mode & S_IFMT)");
break;
}
}
@@ -326,8 +350,8 @@ bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mva
break;
}
case iop_append:
- if (rm == naml->iod->type)
- oflag |= O_APPEND;
+ /* this deviceparameter will move the file pointer to EOF in iorm_open.c
+ but will no longer force write to the EOF, so nothing to do here */
break;
case iop_contiguous:
break;
@@ -529,6 +553,25 @@ bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mva
}
assert(naml->iod->type < n_io_dev_types);
naml->iod->disp_ptr = &io_dev_dispatch[naml->iod->type];
+
+ /* Do this deviceparameter check only if type is rm, it is closed, and no_destroy is defined. If a deviceparameter other
+ * than SEEK or APPEND is defined, then clear no_destroy as state will not be restored.
+ */
+ if ((rm == naml->iod->type) && (dev_closed == naml->iod->state) && ((d_rm_struct *)naml->iod->dev_sp)->no_destroy)
+ {
+ for (p_offset = 0; iop_eol != *(pp->str.addr + p_offset); p_offset += ((IOP_VAR_SIZE == io_params_size[ch])
+ ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]))
+ {
+ ch = *(pp->str.addr + p_offset++);
+ assert((params)ch < (params)n_iops);
+ if ((iop_seek != ch) && (iop_append != ch))
+ {
+ ((d_rm_struct *)naml->iod->dev_sp)->no_destroy = FALSE;
+ break;
+ }
+ }
+ }
+
if (dev_never_opened == naml->iod->state)
{
naml->iod->wrap = DEFAULT_IOD_WRAP;
@@ -538,8 +581,13 @@ bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mva
}
if (dev_open != naml->iod->state)
{
- naml->iod->dollar.x = 0;
- naml->iod->dollar.y = 0;
+ /* initialize x and y unless it is closed and rm and no_destroy is TRUE */
+ if (!((dev_closed == naml->iod->state) && (rm == naml->iod->type) &&
+ ((d_rm_struct *)naml->iod->dev_sp)->no_destroy))
+ {
+ naml->iod->dollar.x = 0;
+ naml->iod->dollar.y = 0;
+ }
naml->iod->dollar.za = 0;
naml->iod->dollar.zb[0] = 0;
naml->iod->dollar.key[0] = 0;
diff --git a/sr_unix/ioff_open.c b/sr_unix/ioff_open.c
index 9edc340..8fb3053 100644
--- a/sr_unix/ioff_open.c
+++ b/sr_unix/ioff_open.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -44,10 +44,11 @@ short ioff_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
d_rm->recordsize = DEF_RM_RECORDSIZE;
d_rm->def_width = d_rm->def_recsize = TRUE;
d_rm->fixed = FALSE;
- d_rm->noread = FALSE;
+ d_rm->read_only = FALSE;
d_rm->padchar = DEF_RM_PADCHAR;
d_rm->inbuf = NULL;
d_rm->outbuf = NULL;
+ d_rm->read_fildes = FD_INVALID;
}
d_rm->fifo = TRUE;
iod->type = rm;
diff --git a/sr_unix/iopi_iocontrol.c b/sr_unix/iopi_iocontrol.c
index fffd9b5..d9ff7a7 100644
--- a/sr_unix/iopi_iocontrol.c
+++ b/sr_unix/iopi_iocontrol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2008, 2013 Fidelity Information Services, Inc *
+ * Copyright 2008, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -24,14 +24,20 @@
#include "gt_timer.h"
#include "gtm_caseconv.h"
#include "min_max.h"
+#include "arit.h"
#include "gtmio.h"
+/* define max strings for $zkey */
+#define MAX_FIXED_STRING (2 * NUM_DEC_DG_2L) + 2
+#define MAX_VAR_STRING NUM_DEC_DG_2L + 1
GBLREF io_pair io_curr_device;
+
error_def(ERR_INVCTLMNE);
+error_def(ERR_IOERROR);
-void iopi_iocontrol(mstr *d)
+void iopi_iocontrol(mstr *mn, int4 argcnt, va_list args)
{
- char action[MAX_DEVCTL_LENGTH];
+ char action[MAX_DEVCTL_LENGTH];
d_rm_struct *d_rm;
int rc;
@@ -40,18 +46,18 @@ void iopi_iocontrol(mstr *d)
if (!d_rm->pipe)
return;
/* we should not get here unless there is some string length after write / */
- assert((int)d->len);
- if (0 == d->len)
+ assertpro((int)mn->len);
+ if (0 == mn->len)
return;
- lower_to_upper((uchar_ptr_t)&action[0], (uchar_ptr_t)d->addr, MIN(d->len, SIZEOF(action)));
- if (0 == memcmp(&action[0], "EOF", MIN(d->len, SIZEOF(action))))
+ lower_to_upper((uchar_ptr_t)&action[0], (uchar_ptr_t)mn->addr, MIN(mn->len, SIZEOF(action)));
+ if (0 == memcmp(&action[0], "EOF", MIN(mn->len, SIZEOF(action))))
{ /* Implement the write /EOF action. Close the output stream to force any blocked output to complete.
* Doing a write /EOF closes the output file descriptor for the pipe device but does not close the
* device. Since the M program could attempt this command more than once, check if the file descriptor
* is already closed before the actual close.
* Ignore the /EOF action if the device is read-only as this is a nop
*/
- if (d_rm->noread)
+ if (d_rm->read_only)
return;
if (FD_INVALID != d_rm->fildes)
{
@@ -59,8 +65,10 @@ void iopi_iocontrol(mstr *d)
* $X will be zero which will keep iorm_readfl() from attempting an iorm_wteol() in the fix mode
* after the file descriptor has been closed.
*/
- iorm_flush(io_curr_device.in);
- CLOSEFILE_RESET(d_rm->fildes, rc); /* resets "d_rm->fildes" to FD_INVALID */
+ iorm_flush(io_curr_device.out);
+ IORM_FCLOSE(d_rm, fildes, filstr);
+ assert(FD_INVALID == d_rm->fildes);
+ assert(NULL == d_rm->filstr);
}
} else
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVCTLMNE);
@@ -69,14 +77,14 @@ void iopi_iocontrol(mstr *d)
void iopi_dlr_device(mstr *d)
{
- io_desc *iod;
- int len;
+ io_desc *iod;
+ int len;
- /* We will default to the output device for setting $device, since pipe uses both */
- iod = io_curr_device.out;
- len = STRLEN(iod->dollar.device);
+ /* We will default to the input device for setting $device, since pipe uses both */
+ iod = io_curr_device.in;
+ len = STRLEN(iod->dollar.device);
/* verify internal buffer has enough space for $DEVICE string value */
- assert((int)d->len > len);
+ assertpro((int)d->len > len);
memcpy(d->addr, iod->dollar.device, MIN(len,d->len));
d->len = len;
return;
@@ -84,16 +92,86 @@ void iopi_dlr_device(mstr *d)
void iopi_dlr_key(mstr *d)
{
- io_desc *iod;
- int len;
+ io_desc *iod;
+ int len;
- iod = io_curr_device.out;
+ iod = io_curr_device.in;
- len = STRLEN(iod->dollar.key);
- /* verify internal buffer has enough space for $KEY string value */
- assert((int)d->len > len);
+ len = STRLEN(iod->dollar.key);
+ /* verify internal buffer has enough space for $KEY string value */
+ assertpro((int)d->len > len);
if (len > 0)
- memcpy(d->addr, iod->dollar.key, MIN(len,d->len));
- d->len = len;
- return;
+ memcpy(d->addr, iod->dollar.key, MIN(len,d->len));
+ d->len = len;
+ return;
+}
+
+void iopi_dlr_zkey(mstr *d)
+{
+ io_desc *iod;
+ int len;
+ d_rm_struct *d_rm;
+ char tname[MAX_FIXED_STRING];
+ uint4 record_num; /* record offset in fixed record file */
+ uint4 record_byte; /* byte offset in fixed record block */
+ boolean_t utf_active;
+ off_t cur_position;
+
+
+ iod = io_curr_device.in;
+ d_rm = (d_rm_struct *)(iod->dev_sp);
+ if (d_rm->fifo || d_rm->pipe || (2 >= d_rm->fildes))
+ d->len = 0;
+ else
+ {
+ /* if last operation was a write we need to get the current location into file_pos */
+ if (RM_WRITE == d_rm->lastop)
+ {
+ /* need to do an lseek to get current location in file */
+ cur_position = lseek(d_rm->fildes, (off_t)0, SEEK_CUR);
+ if ((off_t)-1 == cur_position)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("iopi_dlr_zkey()"), CALLFROM, errno);
+ } else
+ d_rm->file_pos = cur_position;
+ }
+ if (d_rm->fixed)
+ {
+ utf_active = gtm_utf8_mode ? (IS_UTF_CHSET(iod->ichset)) : FALSE;
+ if (!utf_active)
+ {
+ /* for M mode the actual recordsize is in iod->width set by open with
+ recordsize or use with width */
+ record_num = d_rm->file_pos / iod->width;
+ record_byte = d_rm->file_pos % iod->width;
+ } else
+ {
+ record_num = d_rm->file_pos / d_rm->recordsize;
+ /* temporarily save bytes remaining to be read from record */
+ record_byte = (int4)(d_rm->inbuf_top - d_rm->inbuf_off);
+ /* if partially empty then the offset is based on recordsize */
+ if (record_byte)
+ {
+ /* bytes read from the record is recordsize minus bytes remaining to be
+ read from record */
+ record_byte = d_rm->recordsize - record_byte;
+ /* decrement record_num since only partially filled */
+ record_num--;
+ }
+ }
+ SNPRINTF(tname, MAX_FIXED_STRING, "%ld,%ld", record_num, record_byte);
+ } else
+ {
+ record_num = d_rm->file_pos;
+ SNPRINTF(tname, MAX_VAR_STRING, "%ld", record_num);
+ }
+ len = STRLEN(tname);
+ /* verify internal buffer has enough space for $ZKEY string value */
+ assertpro((int)d->len > len);
+ if (0 < len)
+ memcpy(d->addr, tname, MIN(len,d->len));
+ d->len = len;
+ }
+ return;
}
diff --git a/sr_unix/iopi_open.c b/sr_unix/iopi_open.c
index 7946ad8..4b37616 100644
--- a/sr_unix/iopi_open.c
+++ b/sr_unix/iopi_open.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2008, 2013 Fidelity Information Services, Inc *
+ * Copyright 2008, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -43,6 +43,7 @@ LITREF unsigned char io_params_size[];
ZOS_ONLY(GBLREF boolean_t gtm_tag_utf8_as_ascii;)
GBLREF boolean_t gtm_pipe_child;
GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
error_def(ERR_DEVOPENFAIL);
error_def(ERR_SYSCALL);
@@ -203,7 +204,7 @@ int parse_pipe(char *cmd_string, char *ret_token)
} else
{
/* look in $gtm_dist in case not explicitly listed or not in the $PATH variable */
- if (!STRLEN(gtm_dist))
+ if (gtm_dist_ok_to_use)
{
/* build a translated path to command */
SPRINTF(temp, "%s/%s", gtm_dist, token2);
@@ -474,8 +475,11 @@ short iopi_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
}
}
file_des_write = pfd_write[1];
- /*do the fork and exec */
- FORK(cpid); /* BYPASSOK: we exec() immediately, no FORK_CLEAN needed */
+ /* Do the fork and exec but BEFORE that do a FFLUSH(NULL) to make sure any fclose (done in io_rundown
+ * in the child process) does not affect file offsets in this (parent) process' file descriptors
+ */
+ FFLUSH(NULL);
+ FORK(cpid);
if (-1 == cpid)
{
save_errno = errno;
@@ -612,7 +616,8 @@ short iopi_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
ERR_TEXT, 2, LEN_AND_LIT("Error in stream open"), save_errno);
}
d_rm->read_fildes = file_des_read;
- }
+ } else
+ d_rm->read_fildes = FD_INVALID;
SPRINTF(&iod->dollar.key[0], "%d", cpid); /* save in pipe specific structure for $KEY access */
memcpy(iod->dollar.device, "0", SIZEOF("0"));
iod->state = dev_closed;
@@ -624,7 +629,7 @@ short iopi_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
d_rm->recordsize = DEF_RM_RECORDSIZE;
d_rm->def_width = d_rm->def_recsize = TRUE;
d_rm->fixed = FALSE;
- d_rm->noread = FALSE;
+ d_rm->read_only = FALSE;
d_rm->padchar = DEF_RM_PADCHAR;
d_rm->inbuf = NULL;
d_rm->outbuf = NULL;
@@ -697,7 +702,7 @@ short iopi_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
io_ptr->dollar.device[0] = 0;
io_ptr->disp_ptr = iod->disp_ptr;
in_d_rm->fixed = d_rm->fixed;
- in_d_rm->noread = TRUE;
+ in_d_rm->read_only = TRUE;
in_d_rm->padchar = d_rm->padchar;
in_d_rm->inbuf = d_rm->inbuf;
in_d_rm->outbuf = d_rm->outbuf;
diff --git a/sr_unix/iorm_close.c b/sr_unix/iorm_close.c
index d4e7e49..94165bc 100644
--- a/sr_unix/iorm_close.c
+++ b/sr_unix/iorm_close.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -36,9 +36,9 @@ GBLREF io_pair io_std_device;
GBLREF boolean_t gtm_pipe_child;
GBLREF volatile bool out_of_time;
-error_def(ERR_CLOSEFAIL);
error_def(ERR_SYSCALL);
error_def(ERR_DEVPARMTOOSMALL);
+error_def(ERR_IOERROR);
LITREF unsigned char io_params_size[];
@@ -49,7 +49,6 @@ void iorm_close(io_desc *iod, mval *pp)
d_rm_struct *stderr_rm_ptr;
unsigned char c;
char *path, *path2;
- int fclose_res;
int stat_res;
int fstat_res;
struct stat statbuf, fstatbuf;
@@ -61,7 +60,7 @@ void iorm_close(io_desc *iod, mval *pp)
int4 wait_status;
#endif
- int status,rc;
+ int status;
unsigned int *dollarx_ptr;
unsigned int *dollary_ptr;
char *savepath2 = 0;
@@ -70,6 +69,7 @@ void iorm_close(io_desc *iod, mval *pp)
boolean_t rm_rundown = FALSE;
TID timer_id;
int4 pipe_timeout = 2; /* default timeout in sec waiting for waitpid */
+ off_t cur_position;
DCL_THREADGBL_ACCESS;
@@ -98,7 +98,8 @@ void iorm_close(io_desc *iod, mval *pp)
}
iorm_use(iod,pp);
- if (*dollarx_ptr && rm_ptr->lastop == RM_WRITE && !iod->dollar.za)
+ /* We do not want a NEWLINE to be issued by the middle process. */
+ if (!gtm_pipe_child)
iorm_flush(iod);
p_offset = 0;
@@ -172,19 +173,42 @@ void iorm_close(io_desc *iod, mval *pp)
assert(iod->pair.in == iod);
iod->state = dev_closed;
- iod->dollar.zeof = FALSE;
- *dollarx_ptr = 0;
- *dollary_ptr = 0;
- rm_ptr->lastop = RM_NOOP;
- if (rm_ptr->inbuf)
+ /* save no_destroy for disk device */
+ if ((FALSE == rm_destroy) && !rm_ptr->fifo && !rm_ptr->pipe && (2 < rm_ptr->fildes))
{
- free(rm_ptr->inbuf);
- rm_ptr->inbuf = NULL;
- }
- if (rm_ptr->outbuf)
+ rm_ptr->no_destroy = TRUE;
+ /* We can write anywhere in the file so need to save current file pointer for re-open
+ if last operation was a write*/
+ /* if last operation was a write then set file_pos to position after write */
+ if (RM_WRITE == rm_ptr->lastop)
+ {
+ /* need to do an lseek to get current location in file */
+ cur_position = lseek(rm_ptr->fildes, (off_t)0, SEEK_CUR);
+ if ((off_t)-1 == cur_position)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("iorm_close()"), CALLFROM, errno);
+ } else
+ rm_ptr->file_pos = cur_position;
+ }
+
+ } else
{
- free(rm_ptr->outbuf);
- rm_ptr->outbuf = NULL;
+ iod->dollar.zeof = FALSE;
+ *dollarx_ptr = 0;
+ *dollary_ptr = 0;
+ rm_ptr->lastop = RM_NOOP;
+ if (rm_ptr->inbuf)
+ {
+ free(rm_ptr->inbuf);
+ rm_ptr->inbuf = NULL;
+ }
+ if (rm_ptr->outbuf)
+ {
+ free(rm_ptr->outbuf);
+ rm_ptr->outbuf = NULL;
+ }
}
/* Do the close first. If the fclose is done first and we are being called from io_rundown just prior to the execv
@@ -196,37 +220,17 @@ void iorm_close(io_desc *iod, mval *pp)
/* Close the fildes unless this is a direct close of the stderr device */
if (!rm_ptr->stderr_parent)
{
- int save_fd;
/* Before closing a pipe device file descriptor, check if the fd was already closed as part of a "write /eof".
* If so, do not attempt the close now. Only need to free up the device structures.
*/
- if (FD_INVALID != rm_ptr->fildes)
- {
- save_fd = rm_ptr->fildes;
- CLOSEFILE_RESET(rm_ptr->fildes, rc); /* resets "rm_ptr->fildes" to FD_INVALID */
- if (0 != rc)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CLOSEFAIL, 1, save_fd, rc);
- }
- if (rm_ptr->filstr != NULL)
- {
- FCLOSE(rm_ptr->filstr, fclose_res);
- rm_ptr->filstr = NULL;
- }
+ IORM_FCLOSE(rm_ptr, fildes, filstr);
+ assert(FD_INVALID == rm_ptr->fildes);
+ assert(NULL == rm_ptr->filstr);
/* if this is a pipe and read_fildes and read_filstr are set then close them also */
- if (0 < rm_ptr->read_fildes)
- {
- save_fd = rm_ptr->read_fildes;
- CLOSEFILE_RESET(rm_ptr->read_fildes, rc); /* resets "rm_ptr->read_fildes" to FD_INVALID */
- if (0 != rc)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CLOSEFAIL, 1, save_fd, rc);
- }
- if (rm_ptr->read_filstr != NULL)
- {
- FCLOSE(rm_ptr->read_filstr, fclose_res);
- rm_ptr->read_filstr = NULL;
- }
+ IORM_FCLOSE(rm_ptr, read_fildes, read_filstr);
+ assert(FD_INVALID == rm_ptr->read_fildes);
+ assert(NULL == rm_ptr->read_filstr);
}
-
/* reap the forked shell process if a pipe - it will be a zombie, otherwise*/
if (rm_ptr->pipe_pid > 0)
{
@@ -295,7 +299,7 @@ void iorm_close(io_desc *iod, mval *pp)
iorm_close(rm_ptr->stderr_child,pp);
}
}
- if ((rm_destroy || rm_ptr->pipe) && !rm_rundown)
+ if ((rm_destroy || rm_ptr->pipe || rm_ptr->fifo) && !rm_rundown)
remove_rms (iod);
return;
}
diff --git a/sr_unix/iorm_get.c b/sr_unix/iorm_get.c
index ae987e4..14e7f41 100644
--- a/sr_unix/iorm_get.c
+++ b/sr_unix/iorm_get.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc *
+ * Copyright 2006, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,6 +33,7 @@
#include "gtm_utf8.h"
#include "gtm_conv.h"
#endif
+#include "gtmcrypt.h"
GBLREF io_pair io_curr_device;
GBLREF spdesc stringpool;
@@ -106,15 +107,15 @@ int gtm_utf_bomcheck(io_desc *iod, gtm_chset_t *chset, unsigned char *buffer, in
int iorm_get_bom_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, boolean_t timed,
boolean_t *bom_timeout, ABS_TIME end_time)
{
+ int status, fildes;
int4 bytes2read, bytes_read, reclen, bom_bytes2read, bom_bytes_read;
- int status = 0;
gtm_chset_t chset;
d_rm_struct *rm_ptr;
- int fildes;
int4 sleep_left;
int4 sleep_time;
ABS_TIME current_time, time_left;
+ status = 0;
rm_ptr = (d_rm_struct *)(io_ptr->dev_sp);
fildes = rm_ptr->fildes;
@@ -154,7 +155,11 @@ int iorm_get_bom_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout,
/* in follow mode a read will return an EOF if no more bytes are available*/
status = read(fildes, &rm_ptr->bom_buf[rm_ptr->bom_buf_cnt], bom_bytes2read - rm_ptr->bom_buf_cnt);
if (0 < status) /* we read some chars */
- {
+ { /* Decrypt the BOM bytes. */
+ if (rm_ptr->input_encrypted)
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name,
+ &rm_ptr->bom_buf[rm_ptr->bom_buf_cnt], status, NULL);
+ rm_ptr->read_occurred = TRUE;
rm_ptr->bom_buf_cnt += status;
} else if (0 == status) /* end of file */
{
@@ -180,7 +185,7 @@ int iorm_get_bom_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout,
*msec_timeout = (int4)(time_left.at_sec * 1000 + time_left.at_usec / 1000);
/* make sure it terminates with bom_timeout */
- if (!*bom_timeout && !*msec_timeout)
+ if ((!*bom_timeout) && (!*msec_timeout))
*msec_timeout = 1;
sleep_left = *msec_timeout;
sleep_time = MIN(100,sleep_left);
@@ -189,9 +194,7 @@ int iorm_get_bom_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout,
if (0 < sleep_time)
SHORT_SLEEP(sleep_time);
if (outofband)
- {
return 0;
- }
continue; /* for now try and read again if eof or no input ready */
} else /* error returned */
{
@@ -205,9 +208,13 @@ int iorm_get_bom_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout,
PIPE_DEBUG(PRINTF("iorm_get_bom_fl do bomcheck: bom_buf_cnt: %d bom_buf: %o\n",
rm_ptr->bom_buf_cnt,rm_ptr->bom_buf[0]); DEBUGPIPEFLUSH;);
rm_ptr->bom_buf_off = gtm_utf_bomcheck(io_ptr, &io_ptr->ichset, rm_ptr->bom_buf, rm_ptr->bom_buf_cnt);
+ /* Will need to know this for seek and other places */
+ rm_ptr->bom_checked = TRUE;
+ /* save number of bom bytes for use in seek */
+ if (rm_ptr->bom_buf_off)
+ rm_ptr->bom_num_bytes = rm_ptr->bom_buf_off;
rm_ptr->file_pos += rm_ptr->bom_buf_off; /* If there is BOM bytes increment file position by bom_buf_off */
- }
- else if (CHSET_UTF16 == chset) /* if UTF16 default to UTF16BE */
+ } else if (CHSET_UTF16 == chset) /* if UTF16 default to UTF16BE */
io_ptr->ichset = CHSET_UTF16BE;
if (chset != io_ptr->ichset)
{ /* UTF16 changed to UTF16BE or UTF16LE */
@@ -221,7 +228,6 @@ int iorm_get_bom_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout,
}
/* If we are in this routine then it is a fixed utf disk read with rm_ptr->follow = TRUE */
-
int iorm_get_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, boolean_t timed,
boolean_t zint_restart, boolean_t *follow_timeout, ABS_TIME end_time)
{
@@ -265,8 +271,7 @@ int iorm_get_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, bool
bytes2read = rm_ptr->recordsize - bytes_already_read;
/* since it is not a restart bytes_already_read happened in a previous read so save it */
rm_ptr->orig_bytes_already_read = bytes_already_read;
- }
- else
+ } else
{
bytes_already_read = rm_ptr->inbuf_top - rm_ptr->inbuf;
bytes2read = rm_ptr->recordsize - bytes_already_read;
@@ -277,7 +282,7 @@ int iorm_get_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, bool
rm_ptr->inbuf_pos = rm_ptr->inbuf_off = rm_ptr->inbuf;
}
PIPE_DEBUG(PRINTF("iorm_get_fol: bytes2read: %d, bytes_already_read: %d, last_was_timeout: %d, zint_restart: %d\n",
- bytes2read,bytes_already_read,rm_ptr->last_was_timeout,zint_restart); DEBUGPIPEFLUSH;);
+ bytes2read, bytes_already_read, rm_ptr->last_was_timeout, zint_restart); DEBUGPIPEFLUSH;);
PIPE_DEBUG(PRINTF("iorm_get_fol: inbuf: 0x%08lx, top: 0x%08lx, off: 0x%08lx\n", rm_ptr->inbuf, rm_ptr->inbuf_top,
rm_ptr->inbuf_off); DEBUGPIPEFLUSH;);
bytes_read = 0;
@@ -287,8 +292,7 @@ int iorm_get_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, bool
if (!rm_ptr->done_1st_read)
{
PIPE_DEBUG(PRINTF("do iorm_get_bom_fol: bytes2read: %d\n", bytes2read); DEBUGPIPEFLUSH;)
- status = iorm_get_bom_fol(io_ptr, tot_bytes_read, msec_timeout, timed,
- &bom_timeout, end_time);
+ status = iorm_get_bom_fol(io_ptr, tot_bytes_read, msec_timeout, timed, &bom_timeout, end_time);
if (!rm_ptr->done_1st_read && outofband)
{
PIPE_DEBUG(PRINTF("return since iorm_get_bom_fol went outofband\n"); DEBUGPIPEFLUSH;);
@@ -349,10 +353,13 @@ int iorm_get_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, bool
temp = (char *)rm_ptr->inbuf_pos;
do
{
- /* in follow mode a read will return an EOF if no more bytes are available*/
+ /* in follow mode a read will return an EOF if no more bytes are available */
status = read(fildes, temp, (int)bytes2read - bytes_count);
if (0 < status) /* we read some chars */
- {
+ { /* Decrypt whatever we read. */
+ if (rm_ptr->input_encrypted)
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name, temp, status, NULL);
+ rm_ptr->read_occurred = TRUE;
*tot_bytes_read += status;
bytes_count += status;
temp = temp + status;
@@ -391,9 +398,7 @@ int iorm_get_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, bool
break;
continue; /* for now try and read again if eof or no input ready */
} else /* error returned */
- {
break;
- }
} while (bytes_count < bytes2read);
status = bytes_count;
}
@@ -405,13 +410,13 @@ int iorm_get_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, bool
if (0 > status)
{
rm_ptr->inbuf_top = rm_ptr->inbuf_pos += *tot_bytes_read;
- return(0);
+ return 0;
}
else
{
rm_ptr->inbuf_top = rm_ptr->inbuf_pos += status;
if ((rm_ptr->inbuf_pos - rm_ptr->inbuf_off) < rm_ptr->recordsize)
- return(0);
+ return 0;
}
}
/* if some bytes were read prior to timeout then process them as if no timeout occurred */
@@ -502,11 +507,10 @@ int iorm_get_fol(io_desc *io_ptr, int4 *tot_bytes_read, int4 *msec_timeout, bool
int iorm_get_bom(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags, int4 *tot_bytes_read,
TID timer_id, int4 *msec_timeout, boolean_t pipe_zero_timeout)
{
+ int fildes, status = 0;
int4 bytes2read, bytes_read, reclen, bom_bytes2read, bom_bytes_read;
- int status = 0;
gtm_chset_t chset;
d_rm_struct *rm_ptr;
- int fildes;
boolean_t pipe_or_fifo = FALSE;
rm_ptr = (d_rm_struct *)(io_ptr->dev_sp);
@@ -537,12 +541,19 @@ int iorm_get_bom(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags,
DOREADRLTO2(fildes, &rm_ptr->bom_buf[rm_ptr->bom_buf_cnt], 1,
out_of_time, blocked_in, ispipe, flags, status, tot_bytes_read,
timer_id, msec_timeout, pipe_zero_timeout, FALSE, pipe_or_fifo);
+ /* Decrypt the read bytes even if they turned out to not contain a BOM. */
+ if (rm_ptr->input_encrypted && ((status > 0) || ((status < 0) && (*tot_bytes_read > 0))))
+ {
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name, &rm_ptr->bom_buf[rm_ptr->bom_buf_cnt],
+ status > 0 ? status : *tot_bytes_read, NULL);
+ rm_ptr->read_occurred = TRUE;
+ }
PIPE_DEBUG(PRINTF("iorm_get_bom UTF8 DOREADRLTO2: status: %d\n", status); DEBUGPIPEFLUSH;);
/* if status is gt 0 we got one char so see if it's a bom */
if (0 < status)
{
rm_ptr->bom_read_one_done = TRUE;
- /* unless there are 2 characters to follow then it can't be a utf8 bom */
+ /* unless there are 2 characters to follow it can't be a utf8 bom */
if (2 != UTF8_MBFOLLOW(&rm_ptr->bom_buf[rm_ptr->bom_buf_cnt]))
{
rm_ptr->bom_buf_cnt += status;
@@ -552,10 +563,17 @@ int iorm_get_bom(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags,
} else
{
PIPE_DEBUG(PRINTF("DOREADRLTO2: bom_bytes2read: %d, bom_buf_cnt: %d toread: %d\n", bom_bytes2read,
- rm_ptr->bom_buf_cnt,bom_bytes2read - rm_ptr->bom_buf_cnt); DEBUGPIPEFLUSH;);
+ rm_ptr->bom_buf_cnt, bom_bytes2read - rm_ptr->bom_buf_cnt); DEBUGPIPEFLUSH;);
DOREADRLTO2(fildes, &rm_ptr->bom_buf[rm_ptr->bom_buf_cnt], bom_bytes2read - rm_ptr->bom_buf_cnt,
out_of_time, blocked_in, ispipe, flags, status, tot_bytes_read,
timer_id, msec_timeout, pipe_zero_timeout, FALSE, pipe_or_fifo);
+ /* Decrypt the read bytes even if they turned out to not contain a BOM. */
+ if (rm_ptr->input_encrypted && ((status > 0) || ((status < 0) && (*tot_bytes_read > 0))))
+ {
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name, &rm_ptr->bom_buf[rm_ptr->bom_buf_cnt],
+ status > 0 ? status : *tot_bytes_read, NULL);
+ rm_ptr->read_occurred = TRUE;
+ }
}
if (0 > status)
{
@@ -584,6 +602,11 @@ int iorm_get_bom(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags,
PIPE_DEBUG(PRINTF("iorm_get_bom do bomcheck: bom_buf_cnt: %d bom_buf: %o\n",
rm_ptr->bom_buf_cnt,rm_ptr->bom_buf[0]); DEBUGPIPEFLUSH;);
rm_ptr->bom_buf_off = gtm_utf_bomcheck(io_ptr, &io_ptr->ichset, rm_ptr->bom_buf, rm_ptr->bom_buf_cnt);
+ /* Will need to know this for seek and other places */
+ rm_ptr->bom_checked = TRUE;
+ /* save number of bom bytes for use in seek */
+ if (rm_ptr->bom_buf_off)
+ rm_ptr->bom_num_bytes = rm_ptr->bom_buf_off;
rm_ptr->file_pos += rm_ptr->bom_buf_off; /* If there is BOM bytes increment file position by bom_buf_off */
}
else if (CHSET_UTF16 == chset) /* if UTF16 default to UTF16BE */
@@ -648,9 +671,6 @@ int iorm_get(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags, int4
bytes_read = 0;
assert(rm_ptr->bufsize >= rm_ptr->recordsize);
errno = status = 0;
- /* don't reset this if continuing from an interrupt unless we haven't read the bom yet */
-/* if (!rm_ptr->done_1st_read || FALSE == zint_restart)
- rm_ptr->inbuf_pos = rm_ptr->inbuf_off = rm_ptr->inbuf;*/
chset = io_ptr->ichset;
if (!rm_ptr->done_1st_read)
{
@@ -667,7 +687,7 @@ int iorm_get(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags, int4
}
assert(CHSET_UTF16 != chset);
PIPE_DEBUG(PRINTF("iorm_get: bom_buf_cnt: %d bom_buf_off: %d\n",rm_ptr->bom_buf_cnt,rm_ptr->bom_buf_off ); DEBUGPIPEFLUSH;);
- if (0 <= status && rm_ptr->bom_buf_cnt > rm_ptr->bom_buf_off)
+ if ((0 <= status) && (rm_ptr->bom_buf_cnt > rm_ptr->bom_buf_off))
{
PIPE_DEBUG(PRINTF("move bom: status: %d\n", status); DEBUGPIPEFLUSH;);
from_bom = MIN((rm_ptr->bom_buf_cnt - rm_ptr->bom_buf_off), bytes2read);
@@ -686,16 +706,20 @@ int iorm_get(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags, int4
bytes2read,bytes_already_read,zint_restart); DEBUGPIPEFLUSH;);
return 0;
}
- if (0 <= status && 0 < bytes2read)
- {
- /* If it is a pipe and at least one character is read, a timer with timer_id
- passed in from iorm_readfl.c will be started. It is canceled in that
- routine if not expired. Last argument is passed as FALSE(UTF_VAR_PF) since we
- are not doing CHUNK_SIZE read here
- */
+ if ((0 <= status) && (0 < bytes2read))
+ { /* If the device is a PIPE, and we read at least one character, start a timer using timer_id passed by iorm_readfl,
+ * which cancels the timer if the read completes before the time expires. The FALSE argument to DOREADRLTO2
+ * indicates the read is not for a CHUNK_SIZE.
+ */
PIPE_DEBUG(PRINTF("pipeget: bytes2read after bom: %d\n", bytes2read); DEBUGPIPEFLUSH;);
DOREADRLTO2(fildes, rm_ptr->inbuf_pos, (int)bytes2read, out_of_time, blocked_in, ispipe,
flags, status, tot_bytes_read, timer_id, msec_timeout, pipe_zero_timeout, FALSE, pipe_or_fifo);
+ if (rm_ptr->input_encrypted && ((0 < status) || ((status < 0) && (*tot_bytes_read > 0))))
+ { /* Decrypt. */
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name, rm_ptr->inbuf_pos,
+ status > 0 ? status : *tot_bytes_read, NULL);
+ rm_ptr->read_occurred = TRUE;
+ }
}
/* if pipe or fifo and outofband then we didn't finish so just adjust inbuf_top and inbuf_pos and return 0 */
@@ -706,13 +730,13 @@ int iorm_get(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags, int4
if (0 > status)
{
rm_ptr->inbuf_top = rm_ptr->inbuf_pos += *tot_bytes_read;
- return(0);
+ return 0;
}
else
{
rm_ptr->inbuf_top = rm_ptr->inbuf_pos += status;
if ((rm_ptr->inbuf_pos - rm_ptr->inbuf_off) < rm_ptr->recordsize)
- return(0);
+ return 0;
}
}
diff --git a/sr_unix/iorm_open.c b/sr_unix/iorm_open.c
index d6821c0..7f7014a 100644
--- a/sr_unix/iorm_open.c
+++ b/sr_unix/iorm_open.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,10 +21,16 @@
#include "io_params.h"
#include "eintr_wrappers.h"
#include "have_crit.h"
+#include "gtmio.h"
#ifdef __MVS__
#include "gtm_zos_io.h"
#include "gtm_zos_chset.h"
#endif
+#ifdef UNICODE_SUPPORTED
+#include "gtm_conv.h"
+#include "gtm_utf8.h"
+#endif
+#include "gtmcrypt.h"
GBLREF io_pair io_curr_device;
GBLREF boolean_t gtm_utf8_mode;
@@ -32,8 +38,10 @@ ZOS_ONLY(GBLREF boolean_t gtm_tag_utf8_as_ascii;)
#ifdef __MVS__
error_def(ERR_BADTAG);
#endif
+error_def(ERR_CRYPTNOAPPEND);
error_def(ERR_DEVOPENFAIL);
error_def(ERR_TEXT);
+error_def(ERR_IOERROR);
@@ -53,14 +61,19 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
int4 recsize_before;
struct stat statbuf;
int p_offset;
- boolean_t utf_active, def_recsize_before, text_tag, newversion = FALSE;
+ int bom_size_toread;
+ boolean_t utf_active, def_recsize_before, text_tag, newversion;
+ boolean_t closed_nodestroy;
+ boolean_t append;
gtm_chset_t width_chset, dummy_chset;
+ long new_position;
long pipe_buff_size;
-#ifdef __MVS__
+# ifdef __MVS__
int file_tag, obtained_tag, realfiletag;
char *errmsg;
-#endif
+# endif
+ newversion = closed_nodestroy = append = FALSE;
iod = dev_name->iod;
size = 0;
p_offset = 0;
@@ -68,6 +81,7 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
assert(NULL != iod);
assert(0 <= iod->state && n_io_dev_states > iod->state);
assert(rm == iod->type);
+
if (dev_never_opened == iod->state)
{
iod->dev_sp = (void *)malloc(SIZEOF(d_rm_struct));
@@ -80,23 +94,48 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
d_rm->recordsize = DEF_RM_RECORDSIZE;
d_rm->def_width = d_rm->def_recsize = TRUE;
d_rm->fixed = FALSE;
- d_rm->noread = FALSE;
+ d_rm->read_only = FALSE;
d_rm->fifo = FALSE;
d_rm->pipe = FALSE;
d_rm->padchar = DEF_RM_PADCHAR;
d_rm->inbuf = NULL;
d_rm->outbuf = NULL;
d_rm->follow = FALSE;
+ d_rm->no_destroy = FALSE;
+ d_rm->read_fildes = FD_INVALID;
+ d_rm->input_iv.addr = NULL;
+ d_rm->input_iv.len = 0;
+ d_rm->output_iv.addr = NULL;
+ d_rm->output_iv.len = 0;
+ d_rm->input_key.addr = NULL;
+ d_rm->input_key.len = 0;
+ d_rm->output_key.addr = NULL;
+ d_rm->output_key.len = 0;
+ d_rm->input_cipher_handle = GTMCRYPT_INVALID_KEY_HANDLE;
+ d_rm->output_cipher_handle = GTMCRYPT_INVALID_KEY_HANDLE;
+ d_rm->input_encrypted = FALSE;
+ d_rm->output_encrypted = FALSE;
+ d_rm->read_occurred = FALSE;
+ d_rm->write_occurred = FALSE;
} else
+ {
d_rm = (d_rm_struct *)iod->dev_sp;
+ /* remember if device closed by nodestroy in case the no_destroy flag was cleared in io_open_try()
+ due to a deviceparameter other than SEEK on reopen */
+ if ((dev_closed == iod->state) && !d_rm->no_destroy && !d_rm->fifo && !d_rm->pipe && (2 < fd))
+ closed_nodestroy = TRUE;
+ }
if (dev_closed == iod->state)
{
- d_rm->lastop = RM_NOOP;
- d_rm->out_bytes = 0;
- d_rm->crlast = FALSE;
- d_rm->done_1st_read = FALSE;
- d_rm->done_1st_write = FALSE;
- d_rm->follow = FALSE;
+ if (!d_rm->no_destroy)
+ {
+ d_rm->lastop = RM_NOOP;
+ d_rm->out_bytes = 0;
+ d_rm->crlast = FALSE;
+ d_rm->done_1st_read = FALSE;
+ d_rm->done_1st_write = FALSE;
+ d_rm->follow = FALSE;
+ }
assert(0 <= fd);
d_rm->fildes = fd;
FSTAT_FILE(fd, &statbuf, fstat_res);
@@ -115,18 +154,67 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
{ /* Only disable BOM writing if there is something in the file already (not empty) */
d_rm->done_1st_read = FALSE;
d_rm->done_1st_write = FALSE;
+ /* the file is not empty so set file_pos to the size of the file */
+ d_rm->file_pos = size;
}
+ append = TRUE; /* remember so we don't clear file_pos later */
break;
} else if (iop_newversion == ch)
newversion = TRUE;
p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 :
io_params_size[ch]);
}
- if (!d_rm->fifo && !d_rm->pipe && fd != 0)
+ if (!d_rm->fifo && !d_rm->pipe && (2 < fd))
{
- if ((off_t)-1 == (size = lseek(fd, (off_t)0, SEEK_CUR)))
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_DEVOPENFAIL, 2, dev_name->len, dev_name->dollar_io,
- ERR_TEXT, 2, LEN_AND_LIT("Error setting file pointer to the current position"), errno);
+ if (d_rm->no_destroy)
+ {
+ /* if last operation was a write then file position set in iorm_close() */
+ if (RM_WRITE == d_rm->lastop)
+ {
+ new_position = d_rm->file_pos;
+ } else
+ {
+ if ((CHSET_M == iod->ichset) || d_rm->fixed)
+ new_position = d_rm->file_pos;
+ else
+ {
+ new_position = d_rm->file_pos +
+ d_rm->utf_tot_bytes_in_buffer - d_rm->utf_start_pos;
+ }
+ }
+
+ /* lseek to file position for nodestroy */
+ if ((off_t)-1 == (size =lseek (fd, (off_t)new_position, SEEK_SET)))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_DEVOPENFAIL, 2,
+ dev_name->len, dev_name->dollar_io, ERR_TEXT, 2,
+ LEN_AND_LIT("Error setting file pointer to the current position"), errno);
+ } else
+ {
+ if ((off_t)-1 == (size = lseek(fd, (off_t)0, SEEK_CUR)))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_DEVOPENFAIL, 2, dev_name->len,
+ dev_name->dollar_io, ERR_TEXT, 2,
+ LEN_AND_LIT("Error setting file pointer to the current position"), errno);
+ /* clear some status if the close was nodestroy but not saving state. The file pointer
+ will be at the beginning or at the end if append is TRUE */
+ if (closed_nodestroy)
+ {
+ iod->dollar.y = 0;
+ iod->dollar.x = 0;
+ d_rm->lastop = RM_NOOP;
+ d_rm->done_1st_read = d_rm->done_1st_write = d_rm->crlast = FALSE;
+ d_rm->out_bytes = d_rm->bom_buf_cnt = d_rm->bom_buf_off = 0;
+ d_rm->inbuf_top = d_rm->inbuf_off = d_rm->inbuf_pos = d_rm->inbuf;
+ if (!append)
+ d_rm->file_pos = 0;
+ /* Reset temporary buffer so that the next read starts afresh */
+ if (IS_UTF_CHSET(iod->ichset))
+ {
+ DEBUG_ONLY(memset(d_rm->utf_tmp_buffer, 0, CHUNK_SIZE));
+ d_rm->utf_start_pos = 0;
+ d_rm->utf_tot_bytes_in_buffer = 0;
+ }
+ }
+ }
if (size == statbuf.st_size)
iod->dollar.zeof = TRUE;
} else
@@ -147,22 +235,35 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
dev_name->dollar_io, ERR_TEXT, 2,
LEN_AND_LIT("Error in stream open"), errno);
}
+ /* now fseek required for nodestroy if non-fixed M streaming */
+ if (d_rm->no_destroy && !d_rm->fixed && !IS_UTF_CHSET(iod->ichset))
+ {
+ if (-1 == fseek(d_rm->filstr, (long)d_rm->file_pos, SEEK_SET)) /* move input stream */
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("fseek"),
+ RTS_ERROR_LITERAL("REWIND"), CALLFROM, errno);
+ }
+ }
}
}
recsize_before = d_rm->recordsize;
def_recsize_before = d_rm->def_recsize;
+ /* don't change character set on reopen */
+ if (closed_nodestroy)
+ d_rm->no_destroy = TRUE;
iorm_use(iod, pp);
+
/* Now that recordsize and CHSET parms have been handled (if any), set WIDTH if necessary */
if (recsize_before != d_rm->recordsize || def_recsize_before != d_rm->def_recsize)
{ /* record size was specified even if the same value */
- SET_WIDTH_BYTES
+ SET_WIDTH_BYTES;
assert(width_bytes <= d_rm->recordsize); /* or else RECSIZENOTEVEN error would have been issued */
iod->width = d_rm->recordsize;/* we are guaranteed this width will hold at least one character due to above check */
}
/* Now that recordsize and CHSET parms have been handled (if any), allocate the record buffer if needed (utf8 fixed) */
if (dev_closed == iod->state)
{
-#ifdef __MVS__
+# ifdef __MVS__
/* need to get file tag info before set policy which can change what is returned */
if (-1 == gtm_zos_check_tag(fd, &file_tag, &text_tag))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_DEVOPENFAIL, 2, dev_name->len, dev_name->dollar_io, ERR_TEXT,
@@ -173,7 +274,7 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
{ /* not for stdin, stdout, stderr or pipes */
if (iod->newly_created || newversion)
{ /* tag the file. The macros also modify text_tag and file_tag. */
- if (d_rm->fifo && (iod->is_ochset_default || d_rm->noread))
+ if (d_rm->fifo && (iod->is_ochset_default || d_rm->read_only))
{ /* If FIFO, set tag per ichset if no ochset or READONLY */
SET_TAG_FROM_CHSET(iod->ichset, iod->file_chset, TRUE);
} else
@@ -196,7 +297,7 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
} else
{
iod->file_tag = (unsigned int)file_tag; /* save real tag for file */
- if (iod->is_ochset_default || d_rm->noread)
+ if (iod->is_ochset_default || d_rm->read_only)
{ /* set tag per ichset if no ochset or READONLY */
SET_TAG_FROM_CHSET(iod->ichset, dummy_chset, FALSE);
} else
@@ -225,19 +326,37 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
#endif
if (IS_UTF_CHSET(iod->ichset))
{
- assert(NULL == d_rm->inbuf); /* We shouldn't have an existing buffer at this point */
assert(gtm_utf8_mode);
- d_rm->bufsize = d_rm->fixed ? (d_rm->recordsize + 4) : 20; /* +4 for one extra utf8 char */
- d_rm->inbuf = malloc(d_rm->bufsize);
- d_rm->inbuf_pos = d_rm->inbuf_top = d_rm->inbuf_off = d_rm->inbuf; /* Force read first time thru */
+ /* We shouldn't have an existing buffer at this point if not closed nodestroy */
+ if (!d_rm->no_destroy)
+ assert(NULL == d_rm->inbuf);
+ /* if we already have a buffer then we opened previously in UTF char set so only allocate if NULL*/
+ if (NULL == d_rm->inbuf)
+ {
+ d_rm->bufsize = d_rm->fixed ? (d_rm->recordsize + 4) : 20; /* +4 for one extra utf8 char */
+ d_rm->inbuf = malloc(d_rm->bufsize);
+ d_rm->inbuf_pos = d_rm->inbuf_top = d_rm->inbuf_off = d_rm->inbuf;/* Force read first time thru */
+ }
}
if (IS_UTF16_CHSET(iod->ochset))
{
- assert(NULL == d_rm->outbuf); /* We shouldn't have an existing buffer at this point */
- d_rm->outbufsize = d_rm->recordsize + 4;
- d_rm->outbuf = malloc(d_rm->outbufsize);
- d_rm->out_bytes = 0;
+ /* We shouldn't have an existing buffer at this point if not closed nodestroy*/
+ if (!d_rm->no_destroy)
+ assert(NULL == d_rm->outbuf);
+ /* if we already have a buffer then we opened previously in UTF char set so only allocate if NULL*/
+ if (NULL == d_rm->outbuf)
+ {
+ d_rm->outbufsize = d_rm->recordsize + 4;
+ d_rm->outbuf = malloc(d_rm->outbufsize);
+ d_rm->out_bytes = 0;
+ }
}
+ /* Unless NEWVERSION is specified or the file is empty, or the file was CLOSEd with NODESTROY at EOF, we do not
+ * allow APPEND with encryption.
+ */
+ if (d_rm->output_encrypted && append && (!newversion) && (0 != statbuf.st_size) &&
+ (!d_rm->no_destroy || !iod->dollar.zeof))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CRYPTNOAPPEND, 2, dev_name->len, dev_name->dollar_io);
} else
{ /* check for changed recordsize */
if (IS_UTF_CHSET(iod->ichset) && (recsize_before != d_rm->recordsize))
@@ -257,6 +376,99 @@ short iorm_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 time
d_rm->out_bytes = 0;
}
}
+
+ if (!d_rm->bom_checked && !d_rm->fifo && !d_rm->pipe && (2 < fd) && IS_UTF_CHSET(iod->ochset))
+ {
+ /* if file opened with WRITEONLY */
+ if (d_rm->write_only)
+ {
+ /* get the file size again in case it was truncated */
+ FSTAT_FILE(fd, &statbuf, fstat_res);
+ if (-1 == fstat_res)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_DEVOPENFAIL, 2, dev_name->len,
+ dev_name->dollar_io, ERR_TEXT, 2, LEN_AND_LIT("Error in fstat"), errno);
+
+ /* and is not empty generate and error */
+ if (0 < statbuf.st_size)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_DEVOPENFAIL, 2, dev_name->len, dev_name->dollar_io,
+ ERR_TEXT, 2, LEN_AND_LIT("Cannot read BOM from non-empty WRITEONLY file"));
+
+ /* it is empty so set bom_checked as it will be 0 for all
+ but UTF-16 which will be set in iorm_write.c on the first write */
+ else
+ d_rm->bom_checked = TRUE;
+ } else
+ { /* if not a reopen of file, and is not empty and not writeonly, then go to the
+ beginning of the file if BOM bytes available and read the potential BOM */
+ if (!d_rm->no_destroy && (0 < statbuf.st_size) && (!d_rm->input_encrypted))
+ {
+ assert(UTF16BE_BOM_LEN < UTF8_BOM_LEN);
+ if ((CHSET_UTF8 == iod->ichset) && (statbuf.st_size >= UTF8_BOM_LEN))
+ bom_size_toread = UTF8_BOM_LEN;
+ else if (IS_UTF16_CHSET(iod->ichset) && (statbuf.st_size >= UTF16BE_BOM_LEN))
+ bom_size_toread = UTF16BE_BOM_LEN;
+ else
+ bom_size_toread = 0;
+ if (0 < bom_size_toread)
+ {
+ if ((off_t)-1 == lseek(fd, (off_t)0, SEEK_SET))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_DEVOPENFAIL, 2, dev_name->len,
+ dev_name->dollar_io, ERR_TEXT, 2,
+ LEN_AND_LIT("Error setting file pointer to beginning of file"),
+ errno);
+ d_rm->bom_num_bytes = open_get_bom(iod, bom_size_toread);
+ /* move back to previous file position */
+ if ((off_t)-1 == lseek(fd, (off_t)d_rm->file_pos, SEEK_SET))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_DEVOPENFAIL, 2, dev_name->len,
+ dev_name->dollar_io, ERR_TEXT, 2,
+ LEN_AND_LIT("Error setting file pointer to previous file position"),
+ errno);
+
+ }
+ d_rm->bom_checked = TRUE;
+ }
+ }
+ }
+
+
+ if (d_rm->no_destroy)
+ d_rm->no_destroy = FALSE;
iod->state = dev_open;
return TRUE;
}
+
+/* check for BOM in a disk file under the covers during open, seek, or the first read after a write if not already checked */
+int open_get_bom(io_desc *io_ptr, int bom_size)
+{
+ int status = 0;
+ d_rm_struct *rm_ptr;
+ gtm_chset_t chset;
+ int num_bom_bytes;
+
+ rm_ptr = (d_rm_struct *)(io_ptr->dev_sp);
+ assert(UTF16BE_BOM_LEN == UTF16LE_BOM_LEN);
+ assert(!rm_ptr->input_encrypted);
+
+ /* If ichset is UTF-16 save chset to see if it changes */
+ if (UTF16BE_BOM_LEN == bom_size)
+ chset = io_ptr->ichset;
+ DOREADRL(rm_ptr->fildes, &rm_ptr->bom_buf[0], bom_size, status);
+ if (0 > status)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("read"),
+ RTS_ERROR_LITERAL("READING BOM"), CALLFROM, errno);
+ } else if (0 == status)
+ {
+ num_bom_bytes = 0;
+ } else
+ {
+ num_bom_bytes = gtm_utf_bomcheck(io_ptr, &io_ptr->ichset, &rm_ptr->bom_buf[0], bom_size);
+ if ((UTF16BE_BOM_LEN == bom_size) && chset != io_ptr->ichset)
+ {
+ chset = io_ptr->ichset;
+ get_chset_desc(&chset_names[chset]);
+ }
+ }
+ return (num_bom_bytes);
+}
diff --git a/sr_unix/iorm_readfl.c b/sr_unix/iorm_readfl.c
index 7115581..dc16a3f 100644
--- a/sr_unix/iorm_readfl.c
+++ b/sr_unix/iorm_readfl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,14 +33,15 @@
#include "gtm_conv.h"
#include "gtm_utf8.h"
#endif
+#include "gtmcrypt.h"
GBLREF io_pair io_curr_device;
GBLREF spdesc stringpool;
GBLREF volatile bool out_of_time;
GBLREF boolean_t gtm_utf8_mode;
-GBLREF volatile int4 outofband;
-GBLREF mv_stent *mv_chain;
-GBLREF boolean_t dollar_zininterrupt;
+GBLREF volatile int4 outofband;
+GBLREF mv_stent *mv_chain;
+GBLREF boolean_t dollar_zininterrupt;
#ifdef UNICODE_SUPPORTED
LITREF UChar32 u32_line_term[];
LITREF mstr chset_names[];
@@ -50,6 +51,7 @@ error_def(ERR_IOEOF);
error_def(ERR_SYSCALL);
error_def(ERR_ZINTRECURSEIO);
error_def(ERR_DEVICEWRITEONLY);
+error_def(ERR_IOERROR);
#define fl_copy(a, b) (a > b ? b : a)
@@ -78,11 +80,11 @@ void iorm_readfl_badchar(mval *vmvalptr, int datalen, int delimlen, unsigned cha
/* Return how much input we got */
stringpool.free += vmvalptr->str.len;
- if (NULL != strend && NULL != delimptr)
+ if ((NULL != strend) && (NULL != delimptr))
{ /* First find the end of the delimiter (max of 4 bytes) */
if (0 == delimlen)
{
- for (delimend = delimptr; GTM_MB_LEN_MAX >= delimlen && delimend < strend; ++delimend, ++delimlen)
+ for (delimend = delimptr; (GTM_MB_LEN_MAX >= delimlen) && (delimend < strend); ++delimend, ++delimlen)
{
if (UTF8_VALID(delimend, strend, tmplen))
break;
@@ -128,6 +130,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
boolean_t pipe_or_fifo = FALSE;
boolean_t follow_timeout = FALSE;
boolean_t bom_timeout = FALSE;
+ int follow_width;
int blocked_in = TRUE;
int do_clearerr = FALSE;
int saved_lastop;
@@ -142,6 +145,10 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
fd_set input_fds;
int4 sleep_left;
int4 sleep_time;
+ struct stat statbuf;
+ int fstat_res;
+ off_t cur_position;
+ int bom_size_toread;
DCL_THREADGBL_ACCESS;
@@ -176,7 +183,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
if (rm_ptr->pipe || rm_ptr->fifo)
pipe_or_fifo = TRUE;
- PIPE_DEBUG(PRINTF(" %d enter iorm_readfl\n",pid); DEBUGPIPEFLUSH);
+ PIPE_DEBUG(PRINTF(" %d enter iorm_readfl\n", pid); DEBUGPIPEFLUSH);
/* if it is a pipe and it's the stdout returned then we need to get the read file descriptor
from rm_ptr->read_fildes and the stream pointer from rm_ptr->read_filstr */
if ((rm_ptr->pipe ZOS_ONLY(|| rm_ptr->fifo)) && (0 < rm_ptr->read_fildes))
@@ -217,6 +224,78 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
}
}
+ /* if the last operation was a write to a disk, we need to initialize it so file_pos is pointing
+ to the current file position */
+ if (!rm_ptr->fifo && !rm_ptr->pipe && (2 < rm_ptr->fildes) && (RM_WRITE == rm_ptr->lastop))
+ {
+ /* need to do an lseek to get current location in file */
+ cur_position = lseek(rm_ptr->fildes, (off_t)0, SEEK_CUR);
+ if ((off_t)-1 == cur_position)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("iorm_readfl()"), CALLFROM, errno);
+ } else
+ rm_ptr->file_pos = cur_position;
+ /* if not fixed and streaming then need to set the stream to the same place in the file */
+ if (!rm_ptr->fixed && !utf_active)
+ {
+ /* move input stream */
+ if (-1 == fseek(rm_ptr->filstr, (long)rm_ptr->file_pos, SEEK_SET))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("fseek"),
+ RTS_ERROR_LITERAL("iorm_readfl()"), CALLFROM, errno);
+ }
+ }
+
+ *dollary_ptr = 0;
+ *dollarx_ptr = 0;
+ /* Reset temporary buffer so that the next read starts afresh */
+ if (utf_active)
+ {
+ rm_ptr->out_bytes = rm_ptr->bom_buf_cnt = rm_ptr->bom_buf_off = 0;
+ rm_ptr->inbuf_top = rm_ptr->inbuf_off = rm_ptr->inbuf_pos = rm_ptr->inbuf;
+ DEBUG_ONLY(memset(rm_ptr->utf_tmp_buffer, 0, CHUNK_SIZE));
+ rm_ptr->utf_start_pos = 0;
+ rm_ptr->utf_tot_bytes_in_buffer = 0;
+
+ /* If bom not checked yet, not at the beginning of the file and at least UTF16BE_BOM_LEN number of bytes,
+ * then go to the beginning of the file and read the potential BOM. Move back to previous file position
+ * after BOM check. Note that in case of encryption this is the only place where the BOM is read.
+ */
+ if ((!rm_ptr->bom_checked) && (0 < rm_ptr->file_pos) && (!rm_ptr->input_encrypted))
+ {
+ FSTAT_FILE(fildes, &statbuf, fstat_res);
+ if (-1 == fstat_res)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat"),
+ CALLFROM, errno);
+ assert(UTF16BE_BOM_LEN < UTF8_BOM_LEN);
+ if ((CHSET_UTF8 == io_ptr->ichset) && (statbuf.st_size >= UTF8_BOM_LEN))
+ bom_size_toread = UTF8_BOM_LEN;
+ else if (IS_UTF16_CHSET(io_ptr->ichset) && (statbuf.st_size >= UTF16BE_BOM_LEN))
+ bom_size_toread = UTF16BE_BOM_LEN;
+ else
+ bom_size_toread = 0;
+ if (0 < bom_size_toread)
+ {
+ if ((off_t)-1 == lseek(fildes, (off_t)0, SEEK_SET))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("lseek"), RTS_ERROR_LITERAL(
+ "Error setting file pointer to beginning of file"),
+ CALLFROM, errno);
+
+ rm_ptr->bom_num_bytes = open_get_bom(io_ptr, bom_size_toread);
+ /* move back to previous file position */
+ if ((off_t)-1 == lseek(fildes, (off_t)rm_ptr->file_pos, SEEK_SET))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("lseek"), RTS_ERROR_LITERAL(
+ "Error restoring file pointer"), CALLFROM, errno);
+ }
+ rm_ptr->bom_checked = TRUE;
+ }
+ }
+ }
+
zint_restart = FALSE;
/* Check if new or resumed read */
if (rm_ptr->mupintr)
@@ -273,7 +352,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
if (0 == width)
{
width = io_ptr->width; /* called from iorm_read */
- if (!utf_active || !rm_ptr->fixed)
+ if (!rm_ptr->fixed)
max_width = width; /* preserve prior functionality */
} else if (-1 == width)
{
@@ -310,7 +389,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
end_time.at_usec); DEBUGPIPEFLUSH);
PIPE_DEBUG(PRINTF("piperfl: .. buffer address: 0x%08lx stringpool: 0x%08lx\n",
buffer_start, stringpool.free); DEBUGPIPEFLUSH);
- PIPE_DEBUG(PRINTF("buffer_start =%s\n",buffer_start); DEBUGPIPEFLUSH);
+ PIPE_DEBUG(PRINTF("buffer_start =%s\n", buffer_start); DEBUGPIPEFLUSH);
/* If it is fixed and utf mode then we are not doing any mods affecting stringpool during the read and
don't use temp, so skip the following stringpool checks */
if (!utf_active || !rm_ptr->fixed)
@@ -363,30 +442,25 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
msec_timeout = NO_M_TIMEOUT;
assert(!pipeintr->end_time_valid);
} else
- {
- /* For timed input, only one timer will be set in this routine. The first case is for a read x:n
- and the second case is potentially for the pipe device doing a read x:0. If a timer is set, the
- out_of_time variable will start as FALSE. The out_of_time variable will change from FALSE
- to TRUE if the timer exires prior to a read completing. For the read x:0 case for a pipe, an attempt
- is made to read one character in non-blocking mode. If it succeeds then the pipe is set to
- blocking mode and a timer is set. In addition, the blocked_in variable is set to TRUE to prevent
- doing this a second time. If a timer is set, it is checked at the end of this routine
- under the "if (timed)" clause. The timed variable is set to true for both read x:n and x:0, but
- msec_timeout will be 0 for read x:0 case unless it's a pipe and has read one character and started the 1 sec
- timer. */
+ { /* For timed input, this routine starts only one timer. One case is for a READ x:n; another is potentially for the
+ * PIPE device doing a READ x:0. If a timer is set, out_of_time starts as FALSE. If the timer expires prior to a
+ * read completing, the timer handler changes out_of_time to TRUE. In the READ x:0 case for a PIPE, if an attempt to
+ * read one character in non-blocking mode succeeds, we set blocked_in to TRUE (to prevent a 2nd timer), set the
+ * PIPE to blocking mode and start the timer for one second. We set timed to TRUE for both READ x:n and x:0;
+ * msec_timeout is 0 for a READ x:0 unless it's a PIPE which has read one character and started a 1 second timer. If
+ * timed is TRUE, we manage the timer outcome at the end of this routine.
+ */
timed = TRUE;
msec_timeout = timeout2msec(timeout);
if (msec_timeout > 0)
- { /* for the read x:n case a timer started here. It is checked in the (timed) clause
- * at the end of this routine and canceled if it has not expired.
+ { /* For the READ x:n case, start a timer and clean it up in the (timed) clause at the end of this routine if
+ * it has not expired.
*/
sys_get_curr_time(&cur_time);
if (!zint_restart || !pipeintr->end_time_valid)
add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
else
- { /* end_time taken from restart data. Compute what msec_timeout should be so timeout timer
- gets set correctly below.
- */
+ { /* Compute appropriate msec_timeout using end_time from restart data. */
end_time = pipeintr->end_time; /* Restore end_time for timeout */
cur_time = sub_abs_time(&end_time, &cur_time);
if (0 > cur_time.at_sec)
@@ -405,10 +479,9 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
if ((0 < msec_timeout) && !rm_ptr->follow)
start_timer(timer_id, msec_timeout, wake_alarm, 0, NULL);
} else
- {
- /* out_of_time is set to TRUE because no timer is set for read x:0 for any device type at
- this point. It will be set to FALSE for a pipe device if it has read one character as
- described above and set a timer. */
+ { /* Except for the one-character read case with a PIPE device described above, a READ x:0 sets out_of_time to
+ * TRUE.
+ */
out_of_time = TRUE;
FCNTL2(fildes, F_GETFL, flags);
if (0 > flags)
@@ -460,10 +533,13 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
io_ptr->dollar.zeof = FALSE;
do
{
- /* in follow mode a read will return an EOF if no more bytes are available*/
+ /* in follow mode a read will return an EOF if no more bytes are available. */
status = read(fildes, temp, width - bytes_count);
if (0 < status) /* we read some chars */
{
+ if (rm_ptr->input_encrypted)
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name, temp, status, NULL);
+ rm_ptr->read_occurred = TRUE;
tot_bytes_read += status;
rm_ptr->file_pos += status;
bytes_count += status;
@@ -495,7 +571,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
if (!out_of_time && !msec_timeout)
msec_timeout = 1;
sleep_left = msec_timeout;
- sleep_time = MIN(100,sleep_left);
+ sleep_time = MIN(100, sleep_left);
} else
sleep_time = 100;
if (0 < sleep_time)
@@ -537,15 +613,20 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
}
} while (bytes_count < width);
} else
- {
- /* If it is a pipe and at least one character is read, a timer with timer_id
- will be started. It is canceled later in this routine if not expired
- prior to return */
+ { /* If the device is a PIPE, and we read at least one character, start a timer using timer_id. We
+ * cancel that timer later in this routine if it has not expired before the return.
+ */
DOREADRLTO2(fildes, temp, width, out_of_time, &blocked_in, rm_ptr->pipe, flags, status,
&tot_bytes_read, timer_id, &msec_timeout, pipe_zero_timeout, FALSE, pipe_or_fifo);
PIPE_DEBUG(PRINTF(" %d fixed\n", pid); DEBUGPIPEFLUSH);
+ if (rm_ptr->input_encrypted && ((status > 0) || ((status < 0) && (tot_bytes_read > 0))))
+ {
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name, temp,
+ (status > 0) ? status : tot_bytes_read, NULL);
+ rm_ptr->read_occurred = TRUE;
+ }
if (0 > status)
{
if (pipe_or_fifo)
@@ -624,6 +705,9 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
{
inchar = (unsigned char)status;
tot_bytes_read++;
+ if (rm_ptr->input_encrypted)
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name, &inchar, 1, NULL);
+ rm_ptr->read_occurred = TRUE;
rm_ptr->file_pos++;
if (inchar == NATIVE_NL)
{
@@ -669,7 +753,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
if (!out_of_time && !msec_timeout)
msec_timeout = 1;
sleep_left = msec_timeout;
- sleep_time = MIN(100,sleep_left);
+ sleep_time = MIN(100, sleep_left);
} else
sleep_time = 100;
if (0 < sleep_time)
@@ -718,6 +802,9 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
if (EOF != (status = getc(filstr)))
{
tchar = (unsigned char)status;
+ if (rm_ptr->input_encrypted)
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name, &tchar, 1, NULL);
+ rm_ptr->read_occurred = TRUE;
/* force it to process below in case character read is a 0 */
if (!status)
status = 1;
@@ -862,7 +949,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
char_ptr = rm_ptr->inbuf_off;
PIPE_DEBUG(PRINTF("iorm_readfl: inbuf: 0x%08lx, top: 0x%08lx, off: 0x%08lx\n", rm_ptr->inbuf,
- rm_ptr->inbuf_top,rm_ptr->inbuf_off); DEBUGPIPEFLUSH;);
+ rm_ptr->inbuf_top, rm_ptr->inbuf_off); DEBUGPIPEFLUSH;);
PIPE_DEBUG(PRINTF("iorm_readfl: status: %d, width: %d", status, width); DEBUGPIPEFLUSH;);
if (0 < buff_len)
{
@@ -971,7 +1058,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
}
PIPE_DEBUG(PRINTF("1: status: %d bytes2read: %d rm_ptr->utf_start_pos: %d "
"rm_ptr->utf_tot_bytes_in_buffer: %d char_bytes_read: %d add_bytes: %d\n",
- status, bytes2read,rm_ptr->utf_start_pos,rm_ptr->utf_tot_bytes_in_buffer,
+ status, bytes2read, rm_ptr->utf_start_pos, rm_ptr->utf_tot_bytes_in_buffer,
char_bytes_read, add_bytes); DEBUGPIPEFLUSH);
char_start = rm_ptr->inbuf_off;
@@ -1093,9 +1180,14 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
if (rm_ptr->follow && (FALSE == bom_timeout))
{
- /* in follow mode a read will return an EOF if no more bytes are available*/
+ /* In follow mode a read returns an EOF if no more bytes are available. */
status = read(fildes, rm_ptr->utf_tmp_buffer, CHUNK_SIZE);
-
+ if ((rm_ptr->input_encrypted) && (0 < status))
+ {
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name,
+ rm_ptr->utf_tmp_buffer, status, NULL);
+ rm_ptr->read_occurred = TRUE;
+ }
if (0 == status) /* end of file */
{
if ((TRUE == timed) && (0 >= sleep_left))
@@ -1103,14 +1195,14 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
follow_timeout = TRUE;
break;
}
-
- /* if a timed read, sleep the minimum of 100 ms and
- sleep_left. If not a timed read then just sleep
- 100 ms */
+ /* If a timed read, sleep the minimum of 100 ms and sleep_left.
+ * If not a timed read then just sleep 100 ms.
+ */
if (TRUE == timed)
{
/* recalculate msec_timeout and sleep_left as
- &end_time - ¤t_time */
+ * &end_time - ¤t_time.
+ */
/* get the current time */
sys_get_curr_time(¤t_time);
time_left = sub_abs_time(&end_time, ¤t_time);
@@ -1126,7 +1218,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
if (!out_of_time && !msec_timeout)
msec_timeout = 1;
sleep_left = msec_timeout;
- sleep_time = MIN(100,sleep_left);
+ sleep_time = MIN(100, sleep_left);
} else
sleep_time = 100;
if (0 < sleep_time)
@@ -1187,14 +1279,21 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
out_of_time, &blocked_in, rm_ptr->pipe, flags,
status, &utf_tot_bytes_read, timer_id,
&msec_timeout, pipe_zero_timeout, pipe_or_fifo, pipe_or_fifo);
+ if (rm_ptr->input_encrypted && ((0 < status) ||
+ ((status < 0) && (0 < utf_tot_bytes_read))))
+ {
+ READ_ENCRYPTED_DATA(rm_ptr, io_ptr->trans_name,
+ rm_ptr->utf_tmp_buffer,
+ (status > 0) ? status : utf_tot_bytes_read, NULL);
+ rm_ptr->read_occurred = TRUE;
+ }
}
-
PIPE_DEBUG(PRINTF("4: read chunk status: %d utf_tot_bytes_read: %d\n",
status, utf_tot_bytes_read); DEBUGPIPEFLUSH);
- /* if status is -1, then total number of bytes read will be stored
- * in utf_tot_bytes_read. */
- /* if chunk read returned some bytes then ignore outofband. We won't try a
- read again until bytes are processed*/
+ /* If status is -1, then total number of bytes read will be stored in
+ * utf_tot_bytes_read. If chunk read returned some bytes, then ignore outofband.
+ * We won't try a read again until bytes are processed.
+ */
if ((pipe_or_fifo || rm_ptr->follow) && outofband && (0 >= status))
{
PIPE_DEBUG(PRINTF(" %d utf2 stream outofband\n", pid); DEBUGPIPEFLUSH);
@@ -1215,7 +1314,8 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
}
pipeintr->max_bufflen = exp_width;
/* streaming mode uses bytes_count to show how many bytes are in *temp,
- but the interrupt re-entrant code uses bytes_read */
+ * but the interrupt re-entrant code uses bytes_read.
+ */
pipeintr->bytes_read = bytes_count;
pipeintr->bytes2read = bytes2read;
pipeintr->char_count = char_count;
@@ -1232,7 +1332,6 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
assertpro(FALSE); /* Should *never* return from outofband_action */
return FALSE; /* For the compiler.. */
}
-
if (-1 == status)
{
rm_ptr->utf_tot_bytes_in_buffer = utf_tot_bytes_read;
@@ -1245,8 +1344,6 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
} else if (pipe_zero_timeout)
out_of_time = FALSE; /* reset out_of_time for pipe as no actual read is done */
-
-
if (0 <= rm_ptr->utf_tot_bytes_in_buffer)
{
min_bytes_to_copy = MIN(bytes2read,
@@ -1515,9 +1612,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
v->str.len = 0;
v->str.addr = (char *)stringpool.free; /* ensure valid address */
if (EAGAIN != real_errno)
- {
- /* Need to cancel the timer before taking the error return. Otherwise, it will be
- canceled under the (timed) clause below. */
+ { /* Cancel the timer before taking the error return */
if (timed && !out_of_time)
cancel_timer(timer_id);
io_ptr->dollar.za = 9;
@@ -1529,9 +1624,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
}
if (timed)
- {
- /* If a timer was started then msec_timeout will be non-zero so the cancel_timer
- check is done in the else clause. */
+ { /* No timer if msec_timeout is zero, so handle the timer in the else. */
if (msec_timeout == 0)
{
if (!rm_ptr->pipe || FALSE == blocked_in)
@@ -1562,7 +1655,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
{
if (TRUE == io_ptr->dollar.zeof)
io_ptr->dollar.zeof = FALSE; /* no EOF in follow mode */
- return(FALSE);
+ return FALSE;
}
/* on end of file set $za to 9 */
len = SIZEOF(ONE_COMMA_DEV_DET_EOF);
@@ -1592,13 +1685,20 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
ret = FALSE;
}
if (rm_ptr->follow && !rm_ptr->fixed && !line_term_seen)
- ret = FALSE;
+ {
+ if (utf_active)
+ follow_width = char_count;
+ else
+ follow_width = bytes_count;
+ if (!follow_width || (follow_width < width))
+ ret = FALSE;
+ }
if (!utf_active || !rm_ptr->fixed)
{ /* if Unicode and fixed, already setup the mstr */
v->str.len = bytes_count;
v->str.addr = (char *)stringpool.free;
UNICODE_ONLY(v->str.char_len = char_count;)
- if (!utf_active && !rm_ptr->fixed)
+ if (!utf_active)
char_count = bytes_count;
}
if (!rm_ptr->fixed && line_term_seen)
@@ -1608,7 +1708,7 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
} else
{
*dollarx_ptr += char_count;
- if (*dollarx_ptr >= io_ptr->width && io_ptr->wrap)
+ if ((*dollarx_ptr >= io_ptr->width) && (rm_ptr->fixed || io_ptr->wrap))
{
*dollary_ptr += (*dollarx_ptr / io_ptr->width);
if(io_ptr->length)
@@ -1619,6 +1719,6 @@ int iorm_readfl (mval *v, int4 width, int4 timeout) /* timeout in seconds */
}
if (follow_timeout)
ret = FALSE;
- assert(FALSE == rm_ptr->mupintr);
+ assert (FALSE == rm_ptr->mupintr);
return (rm_ptr->pipe && out_of_time) ? FALSE : ret;
}
diff --git a/sr_unix/iorm_use.c b/sr_unix/iorm_use.c
index dd6a2e8..781d9ff 100644
--- a/sr_unix/iorm_use.c
+++ b/sr_unix/iorm_use.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,6 +18,7 @@
#include "gtm_stat.h"
#include "gtm_stdio.h"
#include "gtm_iconv.h"
+#include "gtm_limits.h"
#include "copy.h"
#include "io.h"
@@ -26,28 +27,111 @@
#include "iosp.h"
#include "eintr_wrappers.h"
#include "stringpool.h"
+#include "gtm_stdlib.h"
+#include "min_max.h"
+#include "arit.h"
#ifdef UNICODE_SUPPORTED
#include "gtm_conv.h"
#include "gtm_utf8.h"
#endif
+#include "gtmcrypt.h"
-/* Only want to do fstat() once on this file, not on evry use.
- */
-#define FSTAT_CHECK \
- if (!fstat_done) \
- { \
- FSTAT_FILE(rm_ptr->fildes, &statbuf, fstat_res); \
- if (-1 == fstat_res) \
- { \
- save_errno = errno; \
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat"), \
- CALLFROM, save_errno); \
- } \
- mode = mode1 = statbuf.st_mode; \
- fstat_done = TRUE; \
+/* Only want to do fstat() once on this file, not on every use. */
+#define FSTAT_CHECK(GETMODE) \
+ if (!(GETMODE) || !(fstat_done)) \
+ { \
+ FSTAT_FILE(rm_ptr->fildes, &statbuf, fstat_res); \
+ if (-1 == fstat_res) \
+ { \
+ save_errno = errno; \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, \
+ RTS_ERROR_LITERAL("fstat"), \
+ CALLFROM, save_errno); \
+ } \
+ fstat_done = TRUE; \
+ } \
+ if (GETMODE && !get_mode_done) \
+ { \
+ mode = mode1 = statbuf.st_mode; \
+ get_mode_done = TRUE; \
}
#define IS_PADCHAR_VALID(chset, padchar) (IS_ASCII(padchar))
+/* limit seek string to a signed long long */
+#define LIMIT_SEEK_STR NUM_DEC_DG_2L + 2
+/* define size of early_terminate message */
+
+#define INVALID_SEEK_HEAD "SEEK value "
+
+#define INVALID_SEEK_TAIL " invalid."
+
+/* define max size of SDSEEKERR error string */
+#define MAX_ERROR_SIZE STR_LIT_LEN(INVALID_SEEK_HEAD) + MAXDEVPARLEN + STR_LIT_LEN(INVALID_SEEK_TAIL)
+
+/* output SDSEEKERR error */
+#define OUTPUT_SDSEEKERR(SEEK_STR) \
+{ \
+ SNPRINTF(error_str, MAX_ERROR_SIZE,"%s%s%s", INVALID_SEEK_HEAD, SEEK_STR, INVALID_SEEK_TAIL); \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SDSEEKERR, 2, LEN_AND_STR(error_str)); \
+}
+
+/* Check if the IV for the specified direction has changed. */
+#define IV_CHANGED(DIRECTION, NEW_IV, RM_PTR) \
+ ((NEW_IV.len != RM_PTR->DIRECTION ## _iv.len) \
+ || (0 != memcmp(NEW_IV.addr, RM_PTR->DIRECTION ## _iv.addr, NEW_IV.len)))
+
+/* Check if the key for the specified direction has changed. */
+#define KEY_CHANGED(DIRECTION, NEW_KEY, RM_PTR) \
+ ((NEW_KEY.len != RM_PTR->DIRECTION ## _key.len) \
+ || (0 != memcmp(NEW_KEY.addr, RM_PTR->DIRECTION ## _key.addr, NEW_KEY.len)))
+
+#define GET_ADDR_AND_LEN(ADDR, LEN) \
+ ADDR = (char *)(pp->str.addr + p_offset + 1); \
+ LEN = (int)(*(pp->str.addr + p_offset));
+
+#define GET_LEN_AND_ADDR(ADDR, LEN) \
+ LEN = (int)(*(pp->str.addr + p_offset)); \
+ ADDR = (char *)(pp->str.addr + p_offset + 1);
+
+/* Obtain the key and IV from the KEY field, which is expected to be in the format <key><space><iv>, where iv is optional. */
+#define GET_KEY_AND_IV(DIRECTION) \
+{ \
+ int i, len, encr_key_delim_pos; \
+ \
+ GET_ADDR_AND_LEN(DIRECTION ## _key.addr, DIRECTION ## _key.len); \
+ for (i = 0, encr_key_delim_pos = len = DIRECTION ## _key.len; i < DIRECTION ## _key.len; i++) \
+ { \
+ if (ENCR_KEY_DELIM_CHAR == *((char *)DIRECTION ## _key.addr + i)) \
+ { \
+ encr_key_delim_pos = i + 1; \
+ DIRECTION ## _key.len = i; \
+ break; \
+ } \
+ } \
+ DIRECTION ## _iv.addr = (char *)DIRECTION ## _key.addr + encr_key_delim_pos; \
+ DIRECTION ## _iv.len = len - encr_key_delim_pos; \
+ if (GTMCRYPT_MAX_KEYNAME_LEN <= DIRECTION ## _key.len) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CRYPTKEYTOOBIG, 2, \
+ DIRECTION ## _key.len, GTMCRYPT_MAX_KEYNAME_LEN - 1); \
+ else if (0 < DIRECTION ## _key.len) \
+ DIRECTION ## _key_not_empty = TRUE; \
+ else \
+ DIRECTION ## _key_not_empty = FALSE; \
+ DIRECTION ## _key_entry_present = TRUE; \
+}
+
+#define INIT_CIPHER_CONTEXT(OPERATION, KEY, IV, CIPHER_HANDLE, DEV_NAME) \
+{ \
+ int rv; \
+ \
+ GTMCRYPT_INIT_CIPHER_CONTEXT((KEY).len, (KEY).addr, (IV).len, (IV).addr, \
+ CIPHER_HANDLE, OPERATION, rv); \
+ if (0 != rv) \
+ GTMCRYPT_REPORT_ERROR(rv, rts_error, (DEV_NAME)->len, (DEV_NAME)->dollar_io); \
+}
+
+#define ENCR_KEY_DELIM_CHAR ' '
+
typedef struct
{
@@ -55,13 +139,28 @@ typedef struct
unsigned short grp;
} uic_struct;
-LITREF unsigned char io_params_size[];
-GBLREF boolean_t gtm_utf8_mode;
+LITREF unsigned char io_params_size[];
+GBLREF boolean_t gtm_utf8_mode;
+GBLREF io_pair io_std_device; /* standard device */
+
#ifdef UNICODE_SUPPORTED
-GBLREF UConverter *chset_desc[];
-LITREF mstr chset_names[];
+GBLREF UConverter *chset_desc[];
+LITREF mstr chset_names[];
#endif
+
+enum
+{
+ SEEK_PLUS = 1, /* seek from current position plus offset */
+ SEEK_MINUS, /* seek from current position minus offset */
+ SEEK_ABS /* seek absolute position from start of file */
+};
+
+error_def(ERR_CRYPTKEYTOOBIG);
+error_def(ERR_CRYPTNOKEYSPEC);
+error_def(ERR_CRYPTNOOVERRIDE);
+error_def(ERR_CRYPTNOSEEK);
+error_def(ERR_CRYPTNOTRUNC);
error_def(ERR_DEVPARMNEG);
error_def(ERR_RMWIDTHPOS);
error_def(ERR_RMWIDTHTOOBIG);
@@ -70,35 +169,58 @@ error_def(ERR_SYSCALL);
error_def(ERR_WIDTHTOOSMALL);
error_def(ERR_PADCHARINVALID);
error_def(ERR_IOERROR);
+error_def(ERR_SDSEEKERR);
void iorm_use(io_desc *iod, mval *pp)
{
- boolean_t seen_wrap, fstat_done;
+ boolean_t seen_wrap, fstat_done, get_mode_done, outdevparam;
+ boolean_t input_key_not_empty, output_key_not_empty, input_key_entry_present, output_key_entry_present;
+ boolean_t init_input_encryption, init_output_encryption, reset_input_encryption, reset_output_encryption;
+ boolean_t seek_specified, ichset_specified, ochset_specified, chset_allowed;
unsigned char c;
short mode, mode1;
int4 length, width, width_bytes, recordsize, padchar;
- int fstat_res, save_errno;
+ int fstat_res, save_errno, rv;
d_rm_struct *rm_ptr;
struct stat statbuf;
int p_offset;
mstr chset_mstr;
- boolean_t ichset_specified, ochset_specified, chset_allowed;
gtm_chset_t width_chset, temp_chset;
+ int seek_len;
+ char seek_str[LIMIT_SEEK_STR];
+ char *seek_ptr;
+ int seek_type;
+ long seek_value;
+ long new_position;
+ long current_offset;
+ char *endptr;
+ off_t cur_position;
+ int bom_size_toread;
+ io_log_name *dev_name;
+ mstr input_iv, output_iv, input_key, output_key;
+ char error_str[MAX_ERROR_SIZE];
p_offset = 0;
rm_ptr = (d_rm_struct *)iod->dev_sp;
- seen_wrap = fstat_done = FALSE;
- ichset_specified = ochset_specified = chset_allowed = FALSE;
+ input_key_not_empty = output_key_not_empty = FALSE;
+ input_key_entry_present = output_key_entry_present = FALSE;
+ reset_input_encryption = reset_output_encryption = FALSE;
+ init_input_encryption = init_output_encryption = FALSE;
+ seen_wrap = fstat_done = get_mode_done = outdevparam = FALSE;
+ seek_specified = ichset_specified = ochset_specified = chset_allowed = FALSE;
+ dev_name = iod->trans_name;
if (ZOS_ONLY(TRUE ||) gtm_utf8_mode)
chset_allowed = TRUE;
while (*(pp->str.addr + p_offset) != iop_eol)
{
assert((params) *(pp->str.addr + p_offset) < (params)n_iops);
+ /* need to make sure outdevparam is FALSE for every iteration in case multiple instances of OUTSEEK, etc */
+ if (TRUE == outdevparam)
+ outdevparam = FALSE;
switch (c = *(pp->str.addr + p_offset++))
{
case iop_exception:
- iod->error_handler.len = *(pp->str.addr + p_offset);
- iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
+ GET_LEN_AND_ADDR(iod->error_handler.addr, iod->error_handler.len);
s2pool(&iod->error_handler);
break;
case iop_fixed:
@@ -128,18 +250,18 @@ void iorm_use(io_desc *iod, mval *pp)
iod->length = length;
break;
case iop_w_protection:
- FSTAT_CHECK;
+ FSTAT_CHECK(TRUE);
mode &= ~(0x07);
mode |= *(pp->str.addr + p_offset);
break;
case iop_g_protection:
- FSTAT_CHECK;
+ FSTAT_CHECK(TRUE);
mode &= ~(0x07 << 3);
mode |= *(pp->str.addr + p_offset) << 3;
break;
case iop_s_protection:
case iop_o_protection:
- FSTAT_CHECK;
+ FSTAT_CHECK(TRUE);
mode &= ~(0x07 << 6);
mode |= *(pp->str.addr + p_offset) << 6;
break;
@@ -153,10 +275,10 @@ void iorm_use(io_desc *iod, mval *pp)
}
break;
case iop_readonly:
- rm_ptr->noread = TRUE;
+ rm_ptr->read_only = TRUE;
break;
case iop_noreadonly:
- rm_ptr->noread = FALSE;
+ rm_ptr->read_only = FALSE;
break;
case iop_writeonly:
rm_ptr->write_only = TRUE;
@@ -166,7 +288,7 @@ void iorm_use(io_desc *iod, mval *pp)
break;
case iop_recordsize:
if (dev_open != iod->state || (!IS_UTF_CHSET(iod->ichset) && !IS_UTF_CHSET(iod->ochset)) ||
- (!rm_ptr->done_1st_read && !rm_ptr->done_1st_write))
+ (!rm_ptr->done_1st_read && !rm_ptr->done_1st_write))
{ /* only if not open, not UTF, or no reads or writes yet */
GET_LONG(recordsize, (pp->str.addr + p_offset));
if (recordsize <= 0)
@@ -175,29 +297,70 @@ void iorm_use(io_desc *iod, mval *pp)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_RMWIDTHTOOBIG);
rm_ptr->recordsize = recordsize;
rm_ptr->def_recsize = FALSE;
+ /* for sequential device in fixed M mode, recordsize defines initial width */
+ if (dev_open != iod->state && rm_ptr->fixed && (!rm_ptr->fifo && !rm_ptr->pipe) &&
+ (!IS_UTF_CHSET(iod->ichset) && !IS_UTF_CHSET(iod->ochset)))
+ iod->width = recordsize;
}
break;
+ case iop_outrewind:
+ /* for a non-split device, OUTREWIND, INREWIND, and REWIND are equivalent. For a split device
+ * like $PRINCIPAL INREWIND and REWIND operate on the input side and OUTREWIND operates on the
+ * output side. "op_use" calls iorm_use() for both sides for $PRINCIPAL. Since the input
+ * side of $PRINCIPAL is equal to io_std_device.in we break if OUTREWIND is the device parameter.
+ * A similar check is done on the output side if INREWIND or REWIND is the device parameter.
+ */
+ if ((io_std_device.in == iod))
+ break;
+ outdevparam = TRUE;
+ case iop_inrewind:
case iop_rewind:
- if (iod->state == dev_open && !rm_ptr->fifo && !rm_ptr->pipe && 1 != rm_ptr->fildes)
+ if ((FALSE == outdevparam) && (io_std_device.out == iod))
+ break;
+ if (iod->state == dev_open && !rm_ptr->fifo && !rm_ptr->pipe)
{
- iorm_flush(iod);
- if (lseek(rm_ptr->fildes, (off_t)0, SEEK_SET) == -1)
+ if (-1 == lseek(rm_ptr->fildes, (off_t)0, SEEK_SET))
{
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("lseek"),
- RTS_ERROR_LITERAL("REWIND"), CALLFROM, errno);
+ RTS_ERROR_LITERAL("REWIND"), CALLFROM, errno);
}
- if (fseek(rm_ptr->filstr, (long)0, SEEK_SET) == -1) /* Rewind the input stream */
+
+ /* do fseek if non-fixed streaming and iod doesn't point to io_std_device.out */
+ /* Only necessary for the non-utf input which uses buffered reads */
+ if (!rm_ptr->fixed && !IS_UTF_CHSET(iod->ichset) && (iod != io_std_device.out))
{
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("fseek"),
- RTS_ERROR_LITERAL("REWIND"), CALLFROM, errno);
+ /* if streaming non-utf move to end of file first to force flush of any
+ buffered read io */
+ if (-1 == fseek(rm_ptr->filstr, (long)0, SEEK_END))
+ {
+ save_errno = errno;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("fseek"),
+ RTS_ERROR_LITERAL("REWIND"), CALLFROM, save_errno);
+ }
+
+
+ if (-1 == fseek(rm_ptr->filstr, (long)0, SEEK_SET)) /* Rewind the input stream */
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("fseek"),
+ RTS_ERROR_LITERAL("REWIND"), CALLFROM, errno);
+ }
}
- iod->dollar.zeof = FALSE;
+
+ /* need to do FSTAT_FILE to get file size if not already done */
+ FSTAT_CHECK(FALSE);
+
+ /* if file size is not zero then not at end of file */
+ if (0 != statbuf.st_size)
+ iod->dollar.zeof = FALSE;
+ else
+ iod->dollar.zeof = TRUE;
iod->dollar.y = 0;
iod->dollar.x = 0;
rm_ptr->lastop = RM_NOOP;
rm_ptr->done_1st_read = rm_ptr->done_1st_write = rm_ptr->crlast = FALSE;
rm_ptr->out_bytes = rm_ptr->bom_buf_cnt = rm_ptr->bom_buf_off = 0;
- rm_ptr->inbuf_pos = rm_ptr->inbuf_off = rm_ptr->inbuf;
+ rm_ptr->inbuf_top = rm_ptr->inbuf_off = rm_ptr->inbuf_pos = rm_ptr->inbuf;
rm_ptr->file_pos = 0;
/* Reset temporary buffer so that the next read starts afresh */
if (IS_UTF_CHSET(iod->ichset))
@@ -206,6 +369,13 @@ void iorm_use(io_desc *iod, mval *pp)
rm_ptr->utf_start_pos = 0;
rm_ptr->utf_tot_bytes_in_buffer = 0;
}
+ /* If encrypted, release and acquire the cipher handle once again. This way, we reset the encryption
+ * state to read the encrypted data. Any writes henceforth will issue error (NOTTOEOFOUTPUT) unless
+ * a truncate is also done following the rewind or reads take us to the end of the file.
+ */
+ rm_ptr->read_occurred = FALSE;
+ if (rm_ptr->input_encrypted)
+ reset_input_encryption = TRUE;
}
break;
case iop_stream:
@@ -225,66 +395,166 @@ void iorm_use(io_desc *iod, mval *pp)
}
break;
case iop_truncate:
- if (!rm_ptr->fifo && !rm_ptr->pipe && 1 != rm_ptr->fildes)
+ /* truncate if not a fifo and not a pipe and (it is a non-split device or this is the
+ * output side of a split device)
+ */
+ if (!rm_ptr->fifo && !rm_ptr->pipe && ((iod->pair.in == iod->pair.out) || (io_std_device.out == iod)))
{
int ftruncate_res;
- if (fseek(rm_ptr->filstr, (long)rm_ptr->file_pos, SEEK_SET) == -1)
+ int fc_res;
+ FILE *newstr;
+ int newfd;
+
+ /* don't truncate unless it is a regular file */
+ FSTAT_CHECK(TRUE);
+ if (!(S_IFREG & mode))
+ break;
+ /* If encrypted, we cannot allow a truncate if the file pointer is not positioned at the beginning
+ * or the end of the file, unless there have been no writes.
+ */
+ if ((0 != rm_ptr->file_pos) && (!iod->dollar.zeof)
+ && rm_ptr->output_encrypted && rm_ptr->write_occurred)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CRYPTNOTRUNC, 2,
+ dev_name->len, dev_name->dollar_io);
+ }
+ /* If already open, truncate, close, and reopen the device. */
+ if (dev_open == iod->state)
+ {
+ /* if last operation was a write then set file_pos to position after write */
+ if (RM_WRITE == rm_ptr->lastop)
+ {
+ /* need to do an lseek to get current location in file */
+ cur_position = lseek(rm_ptr->fildes, (off_t)0, SEEK_CUR);
+ if ((off_t)-1 == cur_position)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("TRUNCATE"), CALLFROM, errno);
+ } else
+ rm_ptr->file_pos = cur_position;
+ }
+ FTRUNCATE(rm_ptr->fildes, (off_t)rm_ptr->file_pos, ftruncate_res);
+ if (0 != ftruncate_res)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("ftruncate"),
+ RTS_ERROR_LITERAL("TRUNCATE"), CALLFROM, errno);
+ }
+
+ /* the following is only necessary for a non-split device */
+ if (iod->pair.in == iod->pair.out)
+ {
+ do
+ {
+ newfd = dup(rm_ptr->fildes);
+ } while (-1 == newfd && EINTR == errno);
+ if (-1 == newfd)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
+ RTS_ERROR_LITERAL("dup"), CALLFROM, save_errno);
+
+ if (TRUE == rm_ptr->read_only)
+ {
+ FDOPEN(newstr,newfd,"r");
+ } else if (TRUE == rm_ptr->write_only)
+ {
+ FDOPEN(newstr,newfd,"w");
+ } else
+ FDOPEN(newstr,newfd,"r+");
+
+ CLOSE(rm_ptr->fildes,fc_res);
+ FCLOSE(rm_ptr->filstr,fc_res);
+ rm_ptr->filstr = newstr;
+ rm_ptr->fildes = newfd;
+ }
+ }
+
+ /* the following it only necessary for a non-split device */
+ if (iod->pair.in == iod->pair.out)
{
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("fseek"),
- RTS_ERROR_LITERAL("TRUNCATE"), CALLFROM, errno);
+ if (-1 == fseek(rm_ptr->filstr, (long)rm_ptr->file_pos, SEEK_SET))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("fseek"),
+ RTS_ERROR_LITERAL("TRUNCATE"), CALLFROM, errno);
+ }
}
- if (lseek(rm_ptr->fildes, (off_t)rm_ptr->file_pos, SEEK_SET) == -1)
+ if (-1 == lseek(rm_ptr->fildes, (off_t)rm_ptr->file_pos, SEEK_SET))
{
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("lseek"),
- RTS_ERROR_LITERAL("TRUNCATE"), CALLFROM, errno);
+ RTS_ERROR_LITERAL("TRUNCATE"), CALLFROM, errno);
+ }
+ /* if not open then do the truncate here */
+ if (dev_open != iod->state)
+ {
+ FTRUNCATE(rm_ptr->fildes, (off_t)rm_ptr->file_pos, ftruncate_res);
+ if (0 != ftruncate_res)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("ftruncate"),
+ RTS_ERROR_LITERAL("TRUNCATE"), CALLFROM, errno);
+ }
+
}
- FTRUNCATE(rm_ptr->fildes, (off_t)rm_ptr->file_pos, ftruncate_res);
- if (0 != ftruncate_res)
+ /* If we have truncated to the beginning of the file, we are starting afresh, so even a different
+ * KEY or IV may be specified (hence ...was_encrypted is being set to FALSE).
+ */
+ if (0 == rm_ptr->file_pos)
{
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("ftruncate"),
- RTS_ERROR_LITERAL("TRUNCATE"), CALLFROM, errno);
+ rm_ptr->read_occurred = FALSE;
+ rm_ptr->write_occurred = FALSE;
+ if (rm_ptr->input_encrypted)
+ reset_input_encryption = TRUE;
+ if (rm_ptr->output_encrypted)
+ reset_output_encryption = TRUE;
}
iod->dollar.zeof = TRUE;
/* Reset temporary buffer so that the next read can start afresh */
if (IS_UTF_CHSET(iod->ichset))
{
rm_ptr->inbuf_top = rm_ptr->inbuf_off = rm_ptr->inbuf_pos = rm_ptr->inbuf;
- rm_ptr->out_bytes = rm_ptr->bom_buf_cnt = rm_ptr->bom_buf_off = 0;
+ if (RM_WRITE != rm_ptr->lastop && rm_ptr->fixed)
+ rm_ptr->out_bytes = 0;
+ rm_ptr->bom_buf_cnt = rm_ptr->bom_buf_off = 0;
DEBUG_ONLY(memset(rm_ptr->utf_tmp_buffer, 0, CHUNK_SIZE));
rm_ptr->utf_start_pos = 0;
rm_ptr->utf_tot_bytes_in_buffer = 0;
+ if (RM_WRITE == rm_ptr->lastop && rm_ptr->fixed && iod->dollar.x == iod->width)
+ iod->dollar.x = 0;
if (0 == rm_ptr->file_pos)
{
/* If the truncate size is zero reset done_1st_read and done_1st_write
* to FALSE.
*/
rm_ptr->done_1st_read = rm_ptr->done_1st_write = FALSE;
+ rm_ptr->bom_num_bytes = 0;
+ rm_ptr->bom_checked = 0;
}
}
}
break;
case iop_uic:
+ {
+ unsigned char *ch, ct, *end;
+ int chown_res;
+ uic_struct uic;
+
+ ch = (unsigned char *)pp->str.addr + p_offset;
+ ct = *ch++;
+ end = ch + ct;
+ uic.grp = uic.mem = 0;
+ while ((*ch != ',') && (ch < end))
+ uic.mem = (10 * uic.mem) + (*ch++ - '0');
+ if (*ch == ',')
{
- unsigned char *ch, ct, *end;
- int chown_res;
- uic_struct uic;
-
- ch = (unsigned char *)pp->str.addr + p_offset;
- ct = *ch++;
- end = ch + ct;
- uic.grp = uic.mem = 0;
- while ((*ch != ',') && (ch < end))
- uic.mem = (10 * uic.mem) + (*ch++ - '0');
- if (*ch == ',')
- {
- while (++ch < end)
- uic.grp = (10 * uic.grp) + (*ch - '0');
- }
- CHG_OWNER(iod->trans_name->dollar_io, uic.mem, uic.grp, chown_res);
- if (-1 == chown_res)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) errno);
- break;
+ while (++ch < end)
+ uic.grp = (10 * uic.grp) + (*ch - '0');
}
+ CHG_OWNER(iod->trans_name->dollar_io, uic.mem, uic.grp, chown_res);
+ if (-1 == chown_res)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) errno);
+ break;
+ }
case iop_width:
assert(iod->state == dev_open);
GET_LONG(width, (pp->str.addr + p_offset));
@@ -328,72 +598,69 @@ void iorm_use(io_desc *iod, mval *pp)
iod->wrap = FALSE;
break;
case iop_ipchset:
- {
+ {
#ifdef KEEP_zOS_EBCDIC
- if ( (iconv_t)0 != iod->input_conv_cd )
- {
- ICONV_CLOSE_CD(iod->input_conv_cd);
- }
- SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1));
- if (DEFAULT_CODE_SET != iod->in_code_set)
- ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1),
- INSIDE_CH_SET);
+ if ( (iconv_t)0 != iod->input_conv_cd )
+ {
+ ICONV_CLOSE_CD(iod->input_conv_cd);
+ }
+ SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1));
+ if (DEFAULT_CODE_SET != iod->in_code_set)
+ ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1),
+ INSIDE_CH_SET);
#endif
- if (chset_allowed && (dev_open != iod->state))
- {
- chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
- chset_mstr.len = *(pp->str.addr + p_offset);
- SET_ENCODING(temp_chset, &chset_mstr);
- if (!gtm_utf8_mode && IS_UTF_CHSET(temp_chset))
- break; /* ignore UTF chsets if not utf8_mode */
- iod->ichset = temp_chset;
- ichset_specified = TRUE;
- }
+ if (chset_allowed && (dev_open != iod->state))
+ {
+ GET_ADDR_AND_LEN(chset_mstr.addr, chset_mstr.len);
+ SET_ENCODING(temp_chset, &chset_mstr);
+ if (!gtm_utf8_mode && IS_UTF_CHSET(temp_chset))
+ break; /* ignore UTF chsets if not utf8_mode */
+ iod->ichset = temp_chset;
+ ichset_specified = TRUE;
}
- break;
+ }
+ break;
case iop_opchset:
- {
+ {
#ifdef KEEP_zOS_EBCDIC
- if ( (iconv_t) 0 != iod->output_conv_cd )
- {
- ICONV_CLOSE_CD(iod->output_conv_cd);
- }
- SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1));
- if (DEFAULT_CODE_SET != iod->out_code_set)
- ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET,
- (char *)(pp->str.addr + p_offset + 1));
+ if ( (iconv_t) 0 != iod->output_conv_cd )
+ {
+ ICONV_CLOSE_CD(iod->output_conv_cd);
+ }
+ SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1));
+ if (DEFAULT_CODE_SET != iod->out_code_set)
+ ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET,
+ (char *)(pp->str.addr + p_offset + 1));
#endif
- if (chset_allowed && (dev_open != iod->state))
- {
- chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
- chset_mstr.len = *(pp->str.addr + p_offset);
- SET_ENCODING(temp_chset, &chset_mstr);
- if (!gtm_utf8_mode && IS_UTF_CHSET(temp_chset))
- break; /* ignore UTF chsets if not utf8_mode */
- iod->ochset = temp_chset;
- ochset_specified = TRUE;
- if (gtm_utf8_mode && !IS_PADCHAR_VALID(iod->ochset, rm_ptr->padchar))
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_PADCHARINVALID, 0);
- }
+ if (chset_allowed && (dev_open != iod->state))
+ {
+ GET_ADDR_AND_LEN(chset_mstr.addr, chset_mstr.len);
+ SET_ENCODING(temp_chset, &chset_mstr);
+ if (!gtm_utf8_mode && IS_UTF_CHSET(temp_chset))
+ break; /* ignore UTF chsets if not utf8_mode */
+ iod->ochset = temp_chset;
+ ochset_specified = TRUE;
+ if (gtm_utf8_mode && !IS_PADCHAR_VALID(iod->ochset, rm_ptr->padchar))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_PADCHARINVALID, 0);
}
- break;
+ }
+ break;
case iop_chset:
+ {
+ if (chset_allowed && (dev_open != iod->state))
{
- if (chset_allowed && (dev_open != iod->state))
- {
- chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
- chset_mstr.len = *(pp->str.addr + p_offset);
- SET_ENCODING(temp_chset, &chset_mstr);
- if (!gtm_utf8_mode && IS_UTF_CHSET(temp_chset))
- break; /* ignore UTF chsets if not utf8_mode */
- iod->ochset = temp_chset;
- if (gtm_utf8_mode && !IS_PADCHAR_VALID(iod->ochset, rm_ptr->padchar))
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_PADCHARINVALID, 0);
- iod->ichset = iod->ochset;
- ochset_specified = ichset_specified = TRUE;
- }
+ GET_ADDR_AND_LEN(chset_mstr.addr, chset_mstr.len);
+ SET_ENCODING(temp_chset, &chset_mstr);
+ if (!gtm_utf8_mode && IS_UTF_CHSET(temp_chset))
+ break; /* ignore UTF chsets if not utf8_mode */
+ iod->ochset = temp_chset;
+ if (gtm_utf8_mode && !IS_PADCHAR_VALID(iod->ochset, rm_ptr->padchar))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_PADCHARINVALID, 0);
+ iod->ichset = iod->ochset;
+ ochset_specified = ichset_specified = TRUE;
}
- break;
+ }
+ break;
case iop_m:
if (chset_allowed && (dev_open != iod->state))
{
@@ -422,26 +689,247 @@ void iorm_use(io_desc *iod, mval *pp)
if (!rm_ptr->fifo && !rm_ptr->pipe)
rm_ptr->follow = FALSE;
break;
+ case iop_outseek:
+ /* for a non-split device, OUTSEEK, INSEEK, and SEEK are equivalent. For a split device
+ * like $PRINCIPAL INSEEK and SEEK operate on the input side and OUTSEEK operates on the
+ * output side. "op_use" calls iorm_use() for both sides for $PRINCIPAL. Since the input
+ * side of $PRINCIPAL is equal to io_std_device.in we break if OUTSEEK is the device parameter.
+ * A similar check is done on the output side if INSEEK or SEEK is the device parameter.
+ */
+ if ((io_std_device.in == iod))
+ break;
+ outdevparam = TRUE;
+ case iop_inseek:
+ case iop_seek:
+ if ((FALSE == outdevparam) && (io_std_device.out == iod))
+ break;
+ seek_specified = TRUE;
+ if (!rm_ptr->fifo && !rm_ptr->pipe)
+ {
+ /* need to do FSTAT_FILE to get file size if not already done */
+ FSTAT_CHECK(FALSE);
+
+ /* if file size is not zero then process seek request */
+ if (0 != statbuf.st_size)
+ {
+ /* if last operation was a write then set file_pos to position after write */
+ if (RM_WRITE == rm_ptr->lastop)
+ {
+ /* need to do an lseek to get current location in file */
+ cur_position = lseek(rm_ptr->fildes, (off_t)0, SEEK_CUR);
+ if ((off_t)-1 == cur_position)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("SEEK"), CALLFROM, errno);
+ } else
+ rm_ptr->file_pos = cur_position;
+ }
+ seek_len = MIN(*(pp->str.addr + p_offset), (LIMIT_SEEK_STR - 1));
+ /* if seek_len not greater than zero then it's an error so quit now */
+ if (0 >= seek_len)
+ OUTPUT_SDSEEKERR("\"\"");
+ /* If BOM not already checked and not a fifo or pipe, not a reopen of file, is UTF mode,
+ * file is not empty, and not writeonly, and encryption is not in effect, then go to the
+ * beginning of the file and read the potential BOM.
+ */
+ if ((!rm_ptr->bom_checked) && (!rm_ptr->no_destroy) && (!rm_ptr->fifo) && (!rm_ptr->pipe)
+ && (!rm_ptr->input_encrypted) && (2 < rm_ptr->fildes) && (0 < statbuf.st_size)
+ && IS_UTF_CHSET(iod->ichset) && !rm_ptr->write_only)
+ {
+ assert(UTF16BE_BOM_LEN < UTF8_BOM_LEN);
+ if ((CHSET_UTF8 == iod->ichset) && (statbuf.st_size >= UTF8_BOM_LEN))
+ bom_size_toread = UTF8_BOM_LEN;
+ else if (IS_UTF16_CHSET(iod->ichset) && (statbuf.st_size >= UTF16BE_BOM_LEN))
+ bom_size_toread = UTF16BE_BOM_LEN;
+ else
+ bom_size_toread = 0;
+ if (0 < bom_size_toread)
+ {
+ if ((off_t)-1 == lseek(rm_ptr->fildes, (off_t)0, SEEK_SET))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("SEEK"), CALLFROM, errno);
+ rm_ptr->bom_num_bytes = open_get_bom(iod, bom_size_toread);
+
+ /* move back to previous file position */
+ if ((off_t)-1 == lseek(rm_ptr->fildes, (off_t)rm_ptr->file_pos, SEEK_SET))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("SEEK"), CALLFROM, errno);
+ }
+ rm_ptr->bom_checked = TRUE;
+ }
+ memcpy(seek_str, (char *)(pp->str.addr + p_offset + 1), seek_len);
+ seek_str[seek_len] = '\0';
+ seek_ptr = seek_str;
+ if ('+' == *seek_str)
+ {
+ seek_type = SEEK_PLUS;
+ seek_ptr++; /* skip sign */
+ } else if ('-' == *seek_str)
+ {
+ seek_type = SEEK_MINUS;
+ seek_ptr++; /* skip sign */
+ } else
+ {
+ seek_type = SEEK_ABS;
+ }
+ /* require a digit as the next character to make sure 2 signs not entered */
+ if (!ISDIGIT_ASCII(*seek_ptr))
+ OUTPUT_SDSEEKERR(seek_str);
+ errno = 0; /* not reset if previous failure */
+ seek_value = STRTOL(seek_ptr, &endptr, 10);
+ if (ERANGE == errno)
+ OUTPUT_SDSEEKERR(seek_str);
+ if ('\0' != *endptr)
+ OUTPUT_SDSEEKERR(seek_str);
+
+ if (SEEK_MINUS == seek_type)
+ seek_value = -seek_value;
+
+ /* if fixed then convert record offset to byte offset in file */
+ if (rm_ptr->fixed)
+ {
+ if (IS_UTF_CHSET(iod->ichset))
+ {
+ /* utf reads recordsize so if we only processed part of the record
+ adjust it back to the beginning of the record. */
+ if (rm_ptr->inbuf_top - rm_ptr->inbuf_off)
+ {
+ current_offset = rm_ptr->file_pos - rm_ptr->recordsize;
+ } else
+ current_offset = rm_ptr->file_pos;
+
+ if (!rm_ptr->bom_num_bytes)
+ seek_value *= rm_ptr->recordsize; /* no bom to deal with */
+ else
+ {
+ /* account for bom if absolute seek or relative positive seek
+ and we are at the beginning of the file*/
+ if ((seek_type == SEEK_ABS) ||
+ ((0 == current_offset) && (0 < seek_value)))
+ seek_value = seek_value * rm_ptr->recordsize +
+ rm_ptr->bom_num_bytes;
+ else
+ {
+ if (0 == current_offset)
+ {
+ /* zero or less seek from the
+ beginning of the file */
+ seek_value = -1; /* new_position will be 0 below */
+ } else
+ seek_value *= rm_ptr->recordsize;
+ }
+
+ }
+ } else
+ {
+ current_offset = (rm_ptr->file_pos / iod->width) * iod->width;
+ /* Need to adjust current_offset so we land on a record boundary.
+ If the current_offset is in the middle of the record then adjust
+ it so that a relative +0 lands at the beginning of the record */
+ seek_value *= iod->width;
+ }
+ } else
+ current_offset = rm_ptr->file_pos;
+
+ if (seek_type == SEEK_ABS)
+ new_position = seek_value;
+ else
+ {
+ new_position = current_offset + seek_value;
+ }
+
+ /* limit the range of the new calculated position from zero to the file size */
+ if (0 > new_position)
+ new_position = 0;
+ else if (statbuf.st_size < new_position)
+ new_position = statbuf.st_size;
+ if (-1 == lseek(rm_ptr->fildes, (off_t)new_position, SEEK_SET))
+ {
+ save_errno = errno;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("SEEK"), CALLFROM, save_errno);
+ }
+ /* do fseek if non-fixed streaming and iod doesn't point to io_std_device.out */
+ /* Only necessary for the non-utf input which uses buffered reads */
+ if (!rm_ptr->fixed && !IS_UTF_CHSET(iod->ichset) && (iod != io_std_device.out))
+ {
+ /* if open then move to end of file first to force flush of any buffered read io */
+ if (iod->state == dev_open)
+ {
+ if (-1 == fseek(rm_ptr->filstr, (long)0, SEEK_END))
+ {
+ save_errno = errno;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("fseek"),
+ RTS_ERROR_LITERAL("SEEK"), CALLFROM, save_errno);
+ }
+ }
+ /* move input stream */
+ if (-1 == fseek(rm_ptr->filstr, (long)new_position, SEEK_SET))
+ {
+ save_errno = errno;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7,
+ RTS_ERROR_LITERAL("fseek"),
+ RTS_ERROR_LITERAL("SEEK"), CALLFROM, save_errno);
+ }
+ }
+ if (statbuf.st_size == new_position) /* at end of file */
+ iod->dollar.zeof = TRUE;
+ else
+ {
+ iod->dollar.zeof = FALSE;
+ if (0 == new_position) /* at beginning of file */
+ rm_ptr->done_1st_read = rm_ptr->done_1st_write = rm_ptr->crlast = FALSE;
+ }
+ iod->dollar.y = 0;
+ iod->dollar.x = 0;
+ rm_ptr->lastop = RM_NOOP;
+ rm_ptr->file_pos = new_position;
+ /* Reset temporary buffer so that the next read starts afresh */
+ if (IS_UTF_CHSET(iod->ichset))
+ {
+ /* if not at beginning of file then don't read BOM */
+ rm_ptr->out_bytes = rm_ptr->bom_buf_cnt = rm_ptr->bom_buf_off = 0;
+ rm_ptr->inbuf_top = rm_ptr->inbuf_off = rm_ptr->inbuf_pos = rm_ptr->inbuf;
+ DEBUG_ONLY(memset(rm_ptr->utf_tmp_buffer, 0, CHUNK_SIZE));
+ rm_ptr->utf_start_pos = 0;
+ rm_ptr->utf_tot_bytes_in_buffer = 0;
+ }
+ }
+ }
+ break;
+ case iop_key: /* CAUTION: fall-through */
+ case iop_input_key:
+ GET_KEY_AND_IV(input);
+ if (iop_key != c) /* CAUTION: potential fall-through */
+ break;
+ case iop_output_key:
+ GET_KEY_AND_IV(output);
+ break;
default:
break;
}
p_offset += ((IOP_VAR_SIZE == io_params_size[c]) ?
- (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[c]);
+ (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[c]);
}
if (dev_open != iod->state)
{
- if (!ichset_specified)
+ if (!ichset_specified && !rm_ptr->no_destroy)
{
-#ifdef __MVS__
+# ifdef __MVS__
iod->is_ichset_default = TRUE;
-#endif
+# endif
iod->ichset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M;
}
- if (!ochset_specified)
+ if (!ochset_specified && !rm_ptr->no_destroy)
{
-#ifdef __MVS__
+# ifdef __MVS__
iod->is_ochset_default = TRUE;
-#endif
+# endif
iod->ochset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M;
}
if ((CHSET_M != iod->ichset) && (CHSET_UTF16 != iod->ichset) && (CHSET_MAX_IDX > iod->ichset))
@@ -460,7 +948,154 @@ void iorm_use(io_desc *iod, mval *pp)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_RECSIZENOTEVEN, 1, rm_ptr->recordsize);
}
}
- if (fstat_done && mode != mode1)
+
+ assert(((!rm_ptr->input_encrypted) && (!rm_ptr->output_encrypted)) || (dev_open == iod->state) || rm_ptr->no_destroy);
+ assert((!rm_ptr->input_encrypted) || (0 != rm_ptr->input_key.len));
+ assert((!rm_ptr->output_encrypted) || (0 != rm_ptr->output_key.len));
+
+ if (rm_ptr->input_encrypted)
+ { /* Device's input already encrypted. */
+ if (input_key_entry_present)
+ { /* Input KEY deviceparameter is present. */
+ if (input_key_not_empty)
+ { /* Input KEY is meaningful. */
+ if (KEY_CHANGED(input, input_key, rm_ptr) || IV_CHANGED(input, input_iv, rm_ptr))
+ { /* Requested a new IV or KEY; only allow if no reads have happened. */
+ if (rm_ptr->read_occurred)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOOVERRIDE);
+ else
+ reset_input_encryption = init_input_encryption = TRUE;
+ }
+ } else
+ { /* Encryption requested to be turned off; only allow if there have not been any reads. Also,
+ * a non-empty IV cannot be specified at this time.
+ */
+ if (rm_ptr->read_occurred)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOOVERRIDE);
+ else if (0 != input_iv.len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOKEYSPEC);
+ else
+ {
+ rm_ptr->input_encrypted = FALSE;
+ reset_input_encryption = init_input_encryption = FALSE;
+ if (GTMCRYPT_INVALID_KEY_HANDLE != rm_ptr->input_cipher_handle)
+ GTMCRYPT_REMOVE_CIPHER_CONTEXT(rm_ptr->input_cipher_handle);
+ }
+ }
+ }
+ } else
+ { /* Device's input is not yet encrypted. */
+ if (input_key_entry_present)
+ { /* Only initialize encryption if the input key is not empty. */
+ if (input_key_not_empty)
+ { /* Initialize encryption unless some unencrypted reads have occurred. */
+ if (rm_ptr->read_occurred)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOOVERRIDE);
+ else
+ init_input_encryption = TRUE;
+ } else if (0 != input_iv.len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOKEYSPEC);
+ }
+ }
+
+ if (rm_ptr->output_encrypted)
+ { /* Device's output already encrypted. */
+ if (output_key_entry_present)
+ { /* Input KEY deviceparameter is present. */
+ if (output_key_not_empty)
+ { /* Output KEY is meaningful. */
+ if (KEY_CHANGED(output, output_key, rm_ptr) || IV_CHANGED(output, output_iv, rm_ptr))
+ { /* Requested a new IV or KEY; only allow if no writes have happened. */
+ if (rm_ptr->write_occurred)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOOVERRIDE);
+ else
+ reset_output_encryption = init_output_encryption = TRUE;
+ }
+ } else
+ { /* Encryption requested to be turned off; only allow if there have not been any writes. Also,
+ * a non-empty IV cannot be specified at this time.
+ */
+ if (rm_ptr->write_occurred)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOOVERRIDE);
+ else if (0 != output_iv.len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOKEYSPEC);
+ else
+ {
+ rm_ptr->output_encrypted = FALSE;
+ reset_output_encryption = init_output_encryption = FALSE;
+ if (GTMCRYPT_INVALID_KEY_HANDLE != rm_ptr->output_cipher_handle)
+ GTMCRYPT_REMOVE_CIPHER_CONTEXT(rm_ptr->output_cipher_handle);
+ }
+ }
+ }
+ } else
+ { /* Device's output is not yet encrypted. */
+ if (output_key_entry_present)
+ { /* Only initialize encryption if the output key is not empty. */
+ if (output_key_not_empty)
+ { /* Initialize encryption unless some unencrypted writes have occurred. */
+ if (rm_ptr->write_occurred)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOOVERRIDE);
+ else
+ init_output_encryption = TRUE;
+ } else if (0 != output_iv.len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTNOKEYSPEC);
+ }
+ }
+ assert((!reset_input_encryption) || rm_ptr->input_encrypted);
+ assert((!reset_output_encryption) || rm_ptr->output_encrypted);
+ if ((rm_ptr->input_encrypted || init_input_encryption || reset_input_encryption
+ || rm_ptr->output_encrypted || init_output_encryption || reset_output_encryption) && seek_specified)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CRYPTNOSEEK, 2, dev_name->len, dev_name->dollar_io);
+ if (init_input_encryption || init_output_encryption)
+ { /* First time the device is getting encryption turned on. Initialize encryption and setup the keys. */
+ INIT_PROC_ENCRYPTION(NULL, rv);
+ if (0 != rv)
+ GTMCRYPT_REPORT_ERROR(rv, rts_error, dev_name->len, dev_name->dollar_io);
+ }
+ if (reset_input_encryption && (GTMCRYPT_INVALID_KEY_HANDLE != rm_ptr->input_cipher_handle))
+ {
+ GTMCRYPT_REMOVE_CIPHER_CONTEXT(rm_ptr->input_cipher_handle);
+ }
+ if (init_input_encryption)
+ { /* Get the key handle corresponding to the keyname provided. */
+ INIT_CIPHER_CONTEXT(GTMCRYPT_OP_DECRYPT, input_key, input_iv, rm_ptr->input_cipher_handle, dev_name);
+ rm_ptr->input_encrypted = TRUE;
+ rm_ptr->input_key.addr = input_key.addr;
+ rm_ptr->input_key.len = input_key.len;
+ rm_ptr->input_iv.addr = input_iv.addr;
+ rm_ptr->input_iv.len = input_iv.len;
+ s2pool(&rm_ptr->input_key);
+ s2pool(&rm_ptr->input_iv);
+ } else if (reset_input_encryption)
+ {
+ INIT_CIPHER_CONTEXT(GTMCRYPT_OP_DECRYPT, rm_ptr->input_key, rm_ptr->input_iv,
+ rm_ptr->input_cipher_handle, dev_name);
+ }
+ if (reset_output_encryption && (GTMCRYPT_INVALID_KEY_HANDLE != rm_ptr->output_cipher_handle))
+ {
+ GTMCRYPT_REMOVE_CIPHER_CONTEXT(rm_ptr->output_cipher_handle);
+ }
+ if (init_output_encryption)
+ { /* Get the key handle corresponding to the keyname provided. */
+ INIT_CIPHER_CONTEXT(GTMCRYPT_OP_ENCRYPT, output_key, output_iv, rm_ptr->output_cipher_handle, dev_name);
+ rm_ptr->output_encrypted = TRUE;
+ rm_ptr->output_key.addr = output_key.addr;
+ rm_ptr->output_key.len = output_key.len;
+ rm_ptr->output_iv.addr = output_iv.addr;
+ rm_ptr->output_iv.len = output_iv.len;
+ s2pool(&rm_ptr->output_key);
+ s2pool(&rm_ptr->output_iv);
+ } else if (reset_output_encryption)
+ {
+ INIT_CIPHER_CONTEXT(GTMCRYPT_OP_ENCRYPT, rm_ptr->output_key, rm_ptr->output_iv,
+ rm_ptr->output_cipher_handle, dev_name);
+ }
+ if (init_input_encryption || reset_input_encryption || init_output_encryption || reset_output_encryption)
+ { /* Setup an encryption private buffer of size equal to record size. */
+ REALLOC_CRYPTBUF_IF_NEEDED(rm_ptr->recordsize);
+ }
+ if (get_mode_done && (mode != mode1))
{ /* if the mode has been changed by the qualifiers, reset it */
if (-1 == CHMOD(iod->trans_name->dollar_io, mode))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) errno);
diff --git a/sr_unix/iorm_write.c b/sr_unix/iorm_write.c
index 3db26d8..1c06f8b 100644
--- a/sr_unix/iorm_write.c
+++ b/sr_unix/iorm_write.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -25,16 +25,17 @@
#include "gtm_conv.h"
#include "gtm_utf8.h"
#endif
+#include "gtmcrypt.h"
GBLREF io_pair io_curr_device;
#ifdef UNICODE_SUPPORTED
LITREF mstr chset_names[];
#endif
-#define MAX_WIDTH 65535
-
-error_def(ERR_NOTTOEOFONPUT);
+error_def(ERR_CRYPTBADWRTPOS);
error_def(ERR_DEVICEREADONLY);
+error_def(ERR_IOERROR);
+error_def(ERR_NOTTOEOFONPUT);
error_def(ERR_SYSCALL);
/* write ASCII characters converting to UTF16 if needed
@@ -45,6 +46,7 @@ int iorm_write_utf_ascii(io_desc *iod, char *string, int len)
int outlen, mblen, status;
wint_t utf_code;
unsigned char *outstart, *out, *top, *outptr, *nextoutptr, *outptrtop, *nextmb;
+ char *out_ptr;
d_rm_struct *rm_ptr;
rm_ptr = (d_rm_struct *)iod->dev_sp;
@@ -84,13 +86,21 @@ int iorm_write_utf_ascii(io_desc *iod, char *string, int len)
}
if (0 < outlen)
{
- DOWRITERC(rm_ptr->fildes, outstart, outlen, status);
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(outlen);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, outstart, outlen, pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ } else
+ out_ptr = (char *)outstart;
+ DOWRITERC(rm_ptr->fildes, out_ptr, outlen, status);
if (0 != status)
{
DOLLAR_DEVICE_WRITE(iod, status);
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
+ rm_ptr->write_occurred = TRUE;
rm_ptr->out_bytes += outlen;
}
return outlen;
@@ -101,12 +111,16 @@ void iorm_write_utf(mstr *v)
int4 inchars, char_count; /* in characters */
int4 inlen, outbytes, mblen; /* in bytes */
int4 availwidth, usedwidth, mbwidth; /* in display columns */
- int status, padsize;
+ int status, padsize,fstat_res,save_errno;
wint_t utf_code;
io_desc *iod;
d_rm_struct *rm_ptr;
unsigned char *inptr, *top, *nextmb, *outptr, *nextoutptr, *outstart, temppad, temppadarray[2];
+ char *out_ptr;
boolean_t utf8_active = TRUE; /* needed by GTM_IO_WCWIDTH macro */
+ boolean_t stream, wrap;
+ struct stat statbuf;
+
iod = io_curr_device.out;
rm_ptr = (d_rm_struct *)iod->dev_sp;
@@ -120,15 +134,11 @@ void iorm_write_utf(mstr *v)
if (0 >= inchars)
return;
usedwidth = 0;
- if (rm_ptr->stream && !iod->wrap)
- {
- availwidth = iod->width;
- /* For STREAM and NOWRAP, allow a maximum of "rm_ptr->recordsize" bytes to be written as part of
- * the current WRITE. Any number of future WRITEs to this same record are allowed as long as
- * each of them is within "rm_ptr->recordsize" bytes (truncated otherwise). This means that
- * it does not matter how many bytes we have already written as part of the current record
- * which is "rm_ptr->out_bytes". Reset it to 0 so we can use it for the current WRITE calculations.
- */
+ stream = rm_ptr->stream;
+ wrap = iod->wrap;
+ if (stream && !wrap)
+ { /* For STREAM and NOWRAP, allow the entire record to be written without any record truncations/terminations */
+ availwidth = inlen; /* calculate worst case requirement of width (in chars) to write out input bytes */
rm_ptr->out_bytes = 0;
} else
availwidth = iod->width - iod->dollar.x;
@@ -137,21 +147,47 @@ void iorm_write_utf(mstr *v)
{
outstart = nextoutptr = outptr = &rm_ptr->outbuf[rm_ptr->out_bytes];
if (!rm_ptr->done_1st_write)
- {
+ { /* get the file size */
+ FSTAT_FILE(rm_ptr->fildes, &statbuf, fstat_res);
+ if (-1 == fstat_res)
+ {
+ save_errno = errno;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat"),
+ CALLFROM, save_errno);
+ }
if (CHSET_UTF16 == iod->ochset)
{ /* Write BOM but do not count it towards the bytes in the current record */
- memcpy(outptr, UTF16BE_BOM, UTF16BE_BOM_LEN);
- outbytes = UTF16BE_BOM_LEN;
- outptr += UTF16BE_BOM_LEN;
- DOWRITERC(rm_ptr->fildes, outstart, outbytes, status);
- if (0 != status)
+ /* write BOM if file is empty */
+ if (0 == statbuf.st_size)
{
- DOLLAR_DEVICE_WRITE(iod, status);
- iod->dollar.za = 9;
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
+ memcpy(outptr, UTF16BE_BOM, UTF16BE_BOM_LEN);
+ outbytes = UTF16BE_BOM_LEN;
+ outptr += UTF16BE_BOM_LEN;
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(outbytes);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, outstart, outbytes,
+ pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ } else
+ out_ptr = (char *)outstart;
+ DOWRITERC(rm_ptr->fildes, out_ptr, outbytes, status);
+ if (0 != status)
+ {
+ DOLLAR_DEVICE_WRITE(iod, status);
+ iod->dollar.za = 9;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
+ }
+ rm_ptr->write_occurred = TRUE;
+ outptr = outstart;
+ rm_ptr->out_bytes = outbytes = 0;
+ /* save UTF16BE_BOM_LEN in bom_num_bytes until bom is checked, but don't
+ indicate that bom has been checked - which still needs to be done for reading
+ the exception is if the file was opened WRITEONLY */
+ rm_ptr->bom_num_bytes = UTF16BE_BOM_LEN;
+ if (rm_ptr->write_only)
+ rm_ptr->bom_checked = TRUE;
}
- outptr = outstart;
- rm_ptr->out_bytes = outbytes = 0;
iod->ochset = CHSET_UTF16BE;
get_chset_desc(&chset_names[iod->ochset]);
}
@@ -193,16 +229,23 @@ void iorm_write_utf(mstr *v)
/* Note that "mblen" and "mbwidth" are valid only if "inptr < top".
* This is why they are used after the "inptr >= top" check below
*/
- if (inptr >= top || ((usedwidth + mbwidth) > availwidth) || ((rm_ptr->out_bytes + mblen) > rm_ptr->recordsize))
+ if ((inptr >= top) || ((usedwidth + mbwidth) > availwidth) || ((rm_ptr->out_bytes + mblen) > rm_ptr->recordsize))
{ /* filled to WIDTH or end of input or full record */
if (0 < outbytes)
{
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(outbytes);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, outstart, outbytes, pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ } else
+ out_ptr = (char *)outstart;
if (rm_ptr->fifo || rm_ptr->pipe)
{
- WRITEPIPE(rm_ptr->fildes, rm_ptr->pipe_buff_size, outstart, outbytes, status);
+ WRITEPIPE(rm_ptr->fildes, rm_ptr->pipe_buff_size, out_ptr, outbytes, status);
} else
{
- DOWRITERC(rm_ptr->fildes, outstart, outbytes, status);
+ DOWRITERC(rm_ptr->fildes, out_ptr, outbytes, status);
}
if (0 != status)
{
@@ -210,18 +253,19 @@ void iorm_write_utf(mstr *v)
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
+ rm_ptr->write_occurred = TRUE;
}
iod->dollar.x += usedwidth;
if (inptr >= top)
break; /* end of input */
if (char_count >= inchars)
break; /* end of adjusted input characters */
- if (!rm_ptr->stream || iod->wrap)
- { /* implicit record termination for non-stream files or stream files with the "wrap" option. */
- if (!iod->wrap) /* non-stream device wants NOWRAP, so break right away without writing any more */
+ if (!stream || wrap)
+ { /* implicit record termination for non-stream files or stream files with the "wrap" option. */
+ if (!wrap) /* non-stream device wants NOWRAP, so break right away without writing any more */
break;
- if (!rm_ptr->fixed && iod->wrap)
- iorm_write_utf_ascii(iod, RMEOL, STRLEN(RMEOL));
+ if (!rm_ptr->fixed && wrap)
+ iorm_write_utf_ascii(iod, RMEOL, RMEOL_LEN);
else if (rm_ptr->fixed && rm_ptr->out_bytes < rm_ptr->recordsize)
{ /* padding bytes needed */
temppad = rm_ptr->padchar;
@@ -243,13 +287,22 @@ void iorm_write_utf(mstr *v)
}
for ( ; rm_ptr->out_bytes < rm_ptr->recordsize; rm_ptr->out_bytes += padsize)
{
- DOWRITERC(rm_ptr->fildes, temppadarray, padsize, status);
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(padsize);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, temppadarray, padsize,
+ pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ } else
+ out_ptr = (char *)temppadarray;
+ DOWRITERC(rm_ptr->fildes, out_ptr, padsize, status);
if (0 != status)
{
DOLLAR_DEVICE_WRITE(iod, status);
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
+ rm_ptr->write_occurred = TRUE;
}
assert(rm_ptr->out_bytes == rm_ptr->recordsize);
}
@@ -258,19 +311,10 @@ void iorm_write_utf(mstr *v)
if (iod->length) /* and fixed format requires no padding for wrapped records */
iod->dollar.y %= iod->length;
availwidth = iod->width;
- } else
- { /* STREAM specified with NOWRAP */
- /* We can continue to write even if device width is exceeded since NOWRAP has
- * been specified. But if RECORDSIZE limit has been exceeded then we need to
- * automatically terminate this WRITE (not the RECORD though) and return right away.
- * In order to allow further WRITEs to add to this RECORD, reset rm_ptr->out_bytes to 0.
- */
- if ((rm_ptr->out_bytes + mblen) > rm_ptr->recordsize)
- {
- rm_ptr->out_bytes = 0;
- break;
- }
}
+ /* else STREAM specified with NOWRAP.
+ * We can continue to write even if device width is exceeded since NOWRAP has been specified.
+ */
rm_ptr->out_bytes = 0;
/* For UTF16, since input and output streams ("inptr" and "outstart") point to different buffers,
* the last parsed UTF16 character in "inptr" has not yet been written to "outstart" so
@@ -305,11 +349,14 @@ void iorm_write_utf(mstr *v)
void iorm_write(mstr *v)
{
io_desc *iod;
- char *out;
+ char *out, *out_ptr;
int inlen, outlen, status, len;
d_rm_struct *rm_ptr;
int flags;
int fcntl_res;
+ boolean_t stream, wrap;
+ struct stat statbuf;
+ int fstat_res, save_errno;
iod = io_curr_device.out;
#ifdef __MVS__
@@ -322,12 +369,37 @@ void iorm_write(mstr *v)
#endif
memcpy(iod->dollar.device, "0", SIZEOF("0"));
- if (rm_ptr->noread)
+ if (rm_ptr->read_only)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVICEREADONLY);
- if (!iod->dollar.zeof && !rm_ptr->fifo && !rm_ptr->pipe)
+ if ((!rm_ptr->fifo) && (!rm_ptr->pipe) && rm_ptr->output_encrypted)
{
- iod->dollar.za = 9;
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOTTOEOFONPUT);
+ if (!iod->dollar.zeof)
+ {
+ iod->dollar.za = 9;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOTTOEOFONPUT);
+ } else
+ { /* If there have not been any writes, and input encryption attributes are different from those for output,
+ * and the file is not empty, disallow the write.
+ */
+ if ((!rm_ptr->write_occurred)
+ && ((!rm_ptr->input_encrypted)
+ || (rm_ptr->input_iv.len != rm_ptr->output_iv.len)
+ || memcmp(rm_ptr->input_iv.addr, rm_ptr->output_iv.addr, rm_ptr->input_iv.len)
+ || (((rm_ptr->input_key.len != rm_ptr->output_key.len)
+ || memcmp(rm_ptr->input_key.addr, rm_ptr->output_key.addr, rm_ptr->input_key.len))
+ && (!GTMCRYPT_SAME_KEY(rm_ptr->input_cipher_handle, rm_ptr->output_cipher_handle)))))
+ {
+ FSTAT_FILE(rm_ptr->fildes, &statbuf, fstat_res);
+ if (-1 == fstat_res)
+ {
+ save_errno = errno;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat"),
+ CALLFROM, save_errno);
+ }
+ if (0 != statbuf.st_size)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTBADWRTPOS);
+ }
+ }
}
/* if it's a fifo and not system output/error, last operation was not a write and O_NONBLOCK is not set
@@ -346,6 +418,31 @@ void iorm_write(mstr *v)
}
}
+ if (!rm_ptr->fifo && !rm_ptr->pipe && !rm_ptr->fixed && (2 < rm_ptr->fildes) && (RM_WRITE != rm_ptr->lastop))
+ {
+ /* need to do an lseek to set current location in file */
+ if (-1 == (lseek(rm_ptr->fildes, (off_t)rm_ptr->file_pos, SEEK_SET)))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("iorm_write()"), CALLFROM, errno);
+ }
+ }
+
+
+ /* if current file position is less than bom_num_bytes and it is a disk in utf mode and last op not a WRITE
+ skip past the BOM */
+ if (!rm_ptr->fifo && !rm_ptr->pipe && IS_UTF_CHSET(iod->ochset) && (rm_ptr->file_pos < rm_ptr->bom_num_bytes) &&
+ (2 < rm_ptr->fildes) && (RM_WRITE != rm_ptr->lastop))
+ {
+ /* need to do lseek to skip the BOM before writing*/
+ if (-1 == (lseek(rm_ptr->fildes, (off_t)rm_ptr->bom_num_bytes, SEEK_SET)))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_IOERROR, 7, RTS_ERROR_LITERAL("lseek"),
+ RTS_ERROR_LITERAL("iorm_write()"), CALLFROM, errno);
+ }
+ }
+
+
rm_ptr->lastop = RM_WRITE;
if (IS_UTF_CHSET(iod->ochset))
{
@@ -353,26 +450,34 @@ void iorm_write(mstr *v)
return;
}
inlen = v->len;
- if (rm_ptr->stream && !iod->wrap)
- outlen = iod->width;
- else
- outlen = iod->width - iod->dollar.x;
-
- if (!iod->wrap && inlen > outlen && outlen != MAX_WIDTH)
- inlen = outlen;
if (!inlen)
return;
- if (outlen > inlen)
+ stream = rm_ptr->stream;
+ wrap = iod->wrap;
+ if (stream && !wrap)
outlen = inlen;
+ else
+ {
+ outlen = iod->width - iod->dollar.x;
+ if (!wrap && !stream && (inlen > outlen))
+ inlen = outlen; /* implicit input truncation for non-stream files with the "nowrap" option. */
+ }
for (out = v->addr; ; out += len)
{
len = MIN(inlen, outlen);
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(len);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, out, len, pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ } else
+ out_ptr = out;
if (rm_ptr->fifo || rm_ptr->pipe)
{
- WRITEPIPE(rm_ptr->fildes, rm_ptr->pipe_buff_size, out, len, status);
+ WRITEPIPE(rm_ptr->fildes, rm_ptr->pipe_buff_size, out_ptr, len, status);
} else
{
- DOWRITERC(rm_ptr->fildes, out, len, status);
+ DOWRITERC(rm_ptr->fildes, out_ptr, len, status);
}
if (0 != status)
{
@@ -380,35 +485,36 @@ void iorm_write(mstr *v)
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
+ rm_ptr->write_occurred = TRUE;
iod->dollar.x += len;
- if ((inlen -= len) <= 0)
+ if (0 >= (inlen -= len))
break;
-
- if (!rm_ptr->stream || iod->wrap)
- /* implicit record termination for non-stream files
- * or stream files with the "wrap" option.
- */
- {
- if (!rm_ptr->fixed && iod->wrap)
+ if (!stream || wrap)
+ { /* implicit record termination for non-stream files or stream files with the "wrap" option. */
+ if (!rm_ptr->fixed && wrap)
{
- DOWRITERC(rm_ptr->fildes, RMEOL, STRLEN(RMEOL), status);
+ out_ptr = RMEOL;
+ if (rm_ptr->output_encrypted)
+ {
+ assert(pvt_crypt_buf.len >= RMEOL_LEN);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, out_ptr, RMEOL_LEN, pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ }
+ DOWRITERC(rm_ptr->fildes, out_ptr, RMEOL_LEN, status);
if (0 != status)
{
DOLLAR_DEVICE_WRITE(iod, status);
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
+ rm_ptr->write_occurred = TRUE;
}
-
iod->dollar.x = 0; /* don't use wteol to terminate wrapped records for fixed. */
iod->dollar.y++; /* \n is reserved as an end-of-rec delimiter for variable format */
if (iod->length) /* and fixed format requires no padding for wrapped records */
iod->dollar.y %= iod->length;
-
outlen = iod->width;
}
- if (outlen > inlen)
- outlen = inlen;
}
iod->dollar.za = 0;
return;
diff --git a/sr_unix/iorm_wteol.c b/sr_unix/iorm_wteol.c
index 3ad75e6..3a1d402 100644
--- a/sr_unix/iorm_wteol.c
+++ b/sr_unix/iorm_wteol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -26,24 +26,30 @@
#include "gtm_conv.h"
#include "gtm_utf8.h"
#endif
+#include "gtmcrypt.h"
#ifdef UNICODE_SUPPORTED
LITREF mstr chset_names[];
GBLREF UConverter *chset_desc[];
#endif
-error_def(ERR_NOTTOEOFONPUT);
+
+error_def(ERR_CRYPTBADWRTPOS);
error_def(ERR_DEVICEREADONLY);
+error_def(ERR_NOTTOEOFONPUT);
+error_def(ERR_SYSCALL);
void iorm_wteol(int4 x,io_desc *iod)
{
int i, fixed_pad, fixed_pad_bytes, bytes_per_char, avail_bytes, pad_size, res_size;
int status, outbytes;
- char *outstr, temppad, temppadarray[2];
+ char *outstr, temppad, temppadarray[2], *out_ptr;
d_rm_struct *rm_ptr;
unsigned int *dollarx_ptr;
unsigned int *dollary_ptr;
+ struct stat statbuf;
+ int fstat_res, save_errno;
-#ifdef __MVS__
+# ifdef __MVS__
/* on zos if it is a fifo device then point to the pair.out for $X and $Y */
if (((d_rm_struct *)iod->dev_sp)->fifo)
{
@@ -52,34 +58,67 @@ void iorm_wteol(int4 x,io_desc *iod)
rm_ptr = (d_rm_struct *) (iod->pair.out)->dev_sp;
iod = iod->pair.out;
} else
-#endif
+# endif
{
dollarx_ptr = &(iod->dollar.x);
dollary_ptr = &(iod->dollar.y);
rm_ptr = (d_rm_struct *)iod->dev_sp;
}
- if (rm_ptr->noread)
+ if (rm_ptr->read_only)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVICEREADONLY);
- if (!iod->dollar.zeof && !rm_ptr->fifo && !rm_ptr->pipe)
+ if ((!rm_ptr->fifo) && (!rm_ptr->pipe) && rm_ptr->output_encrypted)
{
- iod->dollar.za = 9;
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOTTOEOFONPUT);
+ if (!iod->dollar.zeof)
+ {
+ iod->dollar.za = 9;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOTTOEOFONPUT);
+ } else
+ { /* If there have not been any writes, and input encryption attributes are different from those for output,
+ * and the file is not empty, disallow the write.
+ */
+ if ((!rm_ptr->write_occurred)
+ && ((!rm_ptr->input_encrypted)
+ || (rm_ptr->input_iv.len != rm_ptr->output_iv.len)
+ || memcmp(rm_ptr->input_iv.addr, rm_ptr->output_iv.addr, rm_ptr->input_iv.len)
+ || (((rm_ptr->input_key.len != rm_ptr->output_key.len)
+ || memcmp(rm_ptr->input_key.addr, rm_ptr->output_key.addr, rm_ptr->input_key.len))
+ && (!GTMCRYPT_SAME_KEY(rm_ptr->input_cipher_handle, rm_ptr->output_cipher_handle)))))
+ {
+ FSTAT_FILE(rm_ptr->fildes, &statbuf, fstat_res);
+ if (-1 == fstat_res)
+ {
+ save_errno = errno;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat"),
+ CALLFROM, save_errno);
+ }
+ if (0 != statbuf.st_size)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CRYPTBADWRTPOS);
+ }
+ }
}
rm_ptr->lastop = RM_WRITE;
-#ifdef __MVS__
+# ifdef __MVS__
if (CHSET_BINARY != iod->process_chset)
{
-#endif
- for (i = 0; i < x ; i++)
+# endif
+ for (i = 0; i < x; i++)
{
-#ifdef UNICODE_SUPPORTED
+# ifdef UNICODE_SUPPORTED
if (IS_UTF_CHSET(iod->ochset))
{
if (!rm_ptr->done_1st_write)
{
if (CHSET_UTF16 == iod->ochset)
{ /* write BE BOM this is in raw bytes */
- DOWRITERL(rm_ptr->fildes, UTF16BE_BOM, UTF16BE_BOM_LEN, res_size);
+ out_ptr = UTF16BE_BOM;
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(UTF16BE_BOM_LEN);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, out_ptr, UTF16BE_BOM_LEN,
+ pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ }
+ DOWRITERL(rm_ptr->fildes, out_ptr, UTF16BE_BOM_LEN, res_size);
if (-1 == res_size)
{
int real_errno = errno;
@@ -87,6 +126,7 @@ void iorm_wteol(int4 x,io_desc *iod)
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) real_errno);
}
+ rm_ptr->write_occurred = TRUE;
iod->ochset = CHSET_UTF16BE;
get_chset_desc(&chset_names[iod->ochset]);
}
@@ -127,29 +167,45 @@ void iorm_wteol(int4 x,io_desc *iod)
}
for ( ; rm_ptr->out_bytes < rm_ptr->recordsize; rm_ptr->out_bytes += bytes_per_char)
{
- DOWRITERC(rm_ptr->fildes, temppadarray, bytes_per_char, status);
+ out_ptr = temppadarray;
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(bytes_per_char);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, out_ptr, bytes_per_char,
+ pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ }
+ DOWRITERC(rm_ptr->fildes, out_ptr, bytes_per_char, status);
if (0 != status)
{
DOLLAR_DEVICE_WRITE(iod, status);
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
+ rm_ptr->write_occurred = TRUE;
}
assert(rm_ptr->out_bytes == rm_ptr->recordsize);
}
} else
{
- iorm_write_utf_ascii(iod, RMEOL,STRLEN(RMEOL));
+ iorm_write_utf_ascii(iod, RMEOL, STRLEN(RMEOL));
}
rm_ptr->out_bytes = 0;
} else
-#endif
+# endif
if (rm_ptr->fixed)
{
for (fixed_pad = iod->width - *dollarx_ptr; fixed_pad > 0; fixed_pad -= res_size)
{
pad_size = (fixed_pad > TAB_BUF_SZ) ? TAB_BUF_SZ : fixed_pad;
- DOWRITERL(rm_ptr->fildes, RM_SPACES_BLOCK, pad_size, res_size);
+ out_ptr = (char *)(RM_SPACES_BLOCK);
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(pad_size);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, out_ptr, pad_size, pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ }
+ DOWRITERL(rm_ptr->fildes, out_ptr, pad_size, res_size);
if (-1 == res_size)
{
int real_errno = errno;
@@ -157,24 +213,33 @@ void iorm_wteol(int4 x,io_desc *iod)
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) real_errno);
}
+ rm_ptr->write_occurred = TRUE;
assert(res_size == pad_size);
}
} else
{
- DOWRITERC(rm_ptr->fildes, RMEOL, STRLEN(RMEOL), status);
+ out_ptr = RMEOL;
+ if (rm_ptr->output_encrypted)
+ {
+ REALLOC_CRYPTBUF_IF_NEEDED(RMEOL_LEN);
+ WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, out_ptr, RMEOL_LEN, pvt_crypt_buf.addr);
+ out_ptr = pvt_crypt_buf.addr;
+ }
+ DOWRITERC(rm_ptr->fildes, out_ptr, RMEOL_LEN, status);
if (0 != status)
{
DOLLAR_DEVICE_WRITE(iod, status);
iod->dollar.za = 9;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
+ rm_ptr->write_occurred = TRUE;
}
*dollarx_ptr = 0;
}
-#ifdef __MVS__
+# ifdef __MVS__
} else
*dollarx_ptr = 0; /* just reset $X for BINARY */
-#endif
+# endif
iod->dollar.za = 0;
*dollary_ptr += x;
if (iod->length)
diff --git a/sr_unix/iormdef.h b/sr_unix/iormdef.h
index 4d8b48f..40143d1 100644
--- a/sr_unix/iormdef.h
+++ b/sr_unix/iormdef.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,14 +12,16 @@
#ifndef IORMDEF_H
#define IORMDEF_H
+#include "gtmcrypt.h" /* For gtmcrypt_key_t below. */
+
#define DEF_RM_WIDTH 32767
#define DEF_RM_RECORDSIZE 32767
#define DEF_RM_LENGTH 66
#define CHUNK_SIZE 512
-#define ONE_COMMA "1,"
-#define ONE_COMMA_UNAVAILABLE "1,Resource temporarily unavailable"
-#define ONE_COMMA_DEV_DET_EOF "1,Device detected EOF"
+#define ONE_COMMA "1,"
+#define ONE_COMMA_UNAVAILABLE "1,Resource temporarily unavailable"
+#define ONE_COMMA_DEV_DET_EOF "1,Device detected EOF"
#define DEF_RM_PADCHAR ' ' /* SPACE */
@@ -58,6 +60,59 @@ int pid;
#define SET_WIDTH_BYTES width_bytes = 1;
#endif
+error_def(ERR_CLOSEFAIL);
+error_def(ERR_CRYPTBADWRTPOS);
+
+#define IORM_FCLOSE(D_RM, FILDES, FILSTR) \
+{ \
+ int fclose_res, rc, save_fd; \
+ \
+ if (NULL != D_RM->FILSTR) \
+ { /* Since FCLOSE also closes the fd, reset FILDES (no need to close it separately). */ \
+ LINUX_ONLY(assert(D_RM->FILDES == D_RM->FILSTR->_fileno);) \
+ FCLOSE(D_RM->FILSTR, fclose_res); \
+ if (0 != fclose_res) \
+ { \
+ save_fd = D_RM->FILDES; \
+ rc = errno; \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CLOSEFAIL, 1, save_fd, rc); \
+ } \
+ D_RM->FILSTR = NULL; \
+ D_RM->FILDES = FD_INVALID; \
+ } else if (FD_INVALID != D_RM->FILDES) \
+ { \
+ save_fd = D_RM->FILDES; \
+ CLOSEFILE_RESET(D_RM->FILDES, rc); /* resets "D_RM->FILDES" to FD_INVALID */ \
+ if (0 != rc) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CLOSEFAIL, 1, save_fd, rc); \
+ } \
+}
+
+#define READ_ENCRYPTED_DATA(DEVICE, NAME, INBUF, INBUF_LEN, OUTBUF) \
+{ \
+ int rv; \
+ \
+ if (INBUF_LEN > 0) \
+ { \
+ GTMCRYPT_ENCRYPT_DECRYPT_WITH_IV(NULL, (DEVICE)->input_cipher_handle, \
+ INBUF, INBUF_LEN, OUTBUF, GTMCRYPT_OP_DECRYPT, GTMCRYPT_IV_CONTINUE, rv); \
+ if (0 != rv) \
+ GTMCRYPT_REPORT_ERROR(rv, rts_error, (NAME)->len, (NAME)->dollar_io); \
+ } \
+}
+
+#define WRITE_ENCRYPTED_DATA(DEVICE, NAME, INBUF, INBUF_LEN, OUTBUF) \
+{ \
+ int rv; \
+ \
+ if (INBUF_LEN > 0) \
+ { \
+ GTMCRYPT_ENCRYPT_DECRYPT_WITH_IV(NULL, (DEVICE)->output_cipher_handle, \
+ INBUF, INBUF_LEN, OUTBUF, GTMCRYPT_OP_ENCRYPT, GTMCRYPT_IV_CONTINUE, rv); \
+ if (0 != rv) \
+ GTMCRYPT_REPORT_ERROR(rv, rts_error, (NAME)->len, (NAME)->dollar_io); \
+ } \
+}
/* Operations for this device type */
#define RM_NOOP 0
@@ -92,22 +147,22 @@ typedef struct dev_pairs {
typedef struct pipe_interrupt_type
{
- ABS_TIME end_time;
+ ABS_TIME end_time;
enum pipe_which who_saved;
- int max_bufflen;
- int bytes_read;
- int bytes2read;
- int char_count;
- int bytes_count;
- int add_bytes;
- boolean_t end_time_valid;
+ int max_bufflen;
+ int bytes_read;
+ int bytes2read;
+ int char_count;
+ int bytes_count;
+ int add_bytes;
+ boolean_t end_time_valid;
struct d_rm_struct *newpipe;
} pipe_interrupt;
typedef struct
{
boolean_t fixed; /* Fixed format file */
- boolean_t noread;
+ boolean_t read_only; /* READONLY specified */
boolean_t write_only; /* WRITEONLY specified */
boolean_t stream;
boolean_t fifo;
@@ -121,6 +176,8 @@ typedef struct
boolean_t def_recsize; /* RECORDSIZE has not been changed */
boolean_t bom_read_one_done; /* If pipe/fifo and UTF8, read one byte to check for bom if not set */
boolean_t follow; /* True if disk read with follow - similar to tail -f on a file */
+ boolean_t no_destroy; /* true if disk and NO_DESTROY on CLOSE and filedes >= 2*/
+ boolean_t bom_checked; /* If disk and UTF8 the bom has been read and bom_num_bytes has been set */
pipe_interrupt pipe_save_state; /* Saved state of interrupted IO */
boolean_t mupintr; /* We were mupip interrupted */
unsigned int lastop; /* Last operation done on file */
@@ -142,6 +199,7 @@ typedef struct
int out_bytes; /* Number of bytes output for this fixed record */
uint4 bom_buf_cnt; /* Count of bytes in BOM buffer */
uint4 bom_buf_off; /* Next available byte in BOM buffer */
+ uint4 bom_num_bytes; /* number of bom bytes read */
unsigned char bom_buf[4]; /* Buffer area for BOM assembly */
unsigned char *inbuf; /* Input buffer area */
unsigned char *inbuf_pos; /* Put next char in inbuf here */
@@ -154,7 +212,17 @@ typedef struct
char utf_tmp_buffer[CHUNK_SIZE]; /* Buffer to store CHUNK bytes */
int utf_tot_bytes_in_buffer; /* Number of bytes read from device, it refers utf_tmp_buffer buffer */
int utf_start_pos; /* Current position in utf_tmp_buffer */
-}d_rm_struct; /* rms */
+ boolean_t write_occurred; /* Flag indicating whether a write has occurred on this device. */
+ boolean_t read_occurred; /* Flag indicating whether a read has occurred on this device. */
+ boolean_t input_encrypted; /* Whether this device's input stream is encrypted or not. */
+ boolean_t output_encrypted; /* Whether this device's output stream is encrypted or not. */
+ mstr input_iv; /* Input Initialization Vector for this device's encryption. */
+ mstr output_iv; /* Output Initialization Vector for this device's encryption. */
+ mstr input_key; /* Name that maps to an input encryption key on disk. */
+ mstr output_key; /* Name that maps to an output encryption key on disk. */
+ gtmcrypt_key_t input_cipher_handle; /* Encryption cipher handle for this device. */
+ gtmcrypt_key_t output_cipher_handle; /* Decryption cipher handle for this device. */
+} d_rm_struct; /* rms */
#ifdef KEEP_zOS_EBCDIC
#define NATIVE_NL 0x15 /* EBCDIC */
@@ -174,5 +242,7 @@ int iorm_get(io_desc *io_ptr, int *blocked_in, boolean_t ispipe, int flags, int4
int iorm_write_utf_ascii(io_desc *iod, char *string, int len);
void iorm_write_utf(mstr *v);
void iorm_readfl_badchar(mval *vmvalptr, int datalen, int delimlen, unsigned char *delimptr, unsigned char *strend);
+int open_get_bom(io_desc *io_ptr, int bom_size);
+int open_get_bom2(io_desc *io_ptr, int max_bom_size );
#endif
diff --git a/sr_unix/iosocket_pass_local.c b/sr_unix/iosocket_pass_local.c
new file mode 100644
index 0000000..a1eddd1
--- /dev/null
+++ b/sr_unix/iosocket_pass_local.c
@@ -0,0 +1,695 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+#include <errno.h>
+#ifdef __sun
+#include <ucred.h>
+#endif
+#include "gtm_socket.h"
+#include "gtm_unistd.h"
+#include "io_params.h"
+#include "io.h"
+#include "iotimer.h"
+#include "wake_alarm.h"
+#include "iosocketdef.h"
+#include "min_max.h"
+#include "gtm_netdb.h"
+#include "gtm_stdlib.h"
+#include "gtm_string.h"
+#include "eintr_wrappers.h"
+#include "stringpool.h"
+#include "outofband.h"
+
+#define MAX_PASS_FDS 256
+#define PID_CHECKING_SUPPORTED defined(__linux__) || defined(__sun) || defined(_AIX)
+
+#define RECVALL(FD, BUF, BUFLEN, RVAL) XFERALL(recv, FD, BUF, BUFLEN, RVAL)
+#define SENDALL(FD, BUF, BUFLEN, RVAL) XFERALL(send, FD, BUF, BUFLEN, RVAL)
+
+#define XFERALL(XFOP, FD, BUF, BUFLEN, RVAL) \
+{ \
+ int xf_fd = (FD); \
+ unsigned char *xf_buf = (unsigned char *)(BUF); \
+ size_t xf_buflen = (BUFLEN), xf_xfercnt = 0; \
+ ssize_t xf_rval = 0; \
+ \
+ while (!outofband && !out_of_time && (xf_buflen > xf_xfercnt)) \
+ { \
+ xf_rval = (XFOP)(xf_fd, xf_buf + xf_xfercnt, xf_buflen - xf_xfercnt, 0); \
+ if (-1 == xf_rval) \
+ { \
+ if (EINTR == errno) \
+ continue; \
+ else \
+ break; \
+ } \
+ else if (0 == xf_rval) \
+ { \
+ xf_rval = -1; \
+ errno = ECONNRESET; \
+ break; \
+ } \
+ xf_xfercnt += xf_rval; \
+ } \
+ if (outofband || out_of_time) \
+ { \
+ xf_rval = -1; \
+ errno = EINTR; \
+ } \
+ RVAL = (-1 == xf_rval) ? (ssize_t)-1 : (ssize_t)xf_xfercnt; \
+}
+
+#define PASS_COMPLETE "PASS_COMPLETE"
+#define ACCEPT_COMPLETE "ACCEPT_COMPLETE"
+#define PROTOCOL_ERROR "Protocol Error"
+
+#define DOLLAR_DEVICE_PREFIX "1,"
+
+GBLREF d_socket_struct *socket_pool;
+GBLREF io_pair io_std_device;
+GBLREF int4 gtm_max_sockets;
+GBLREF spdesc stringpool;
+GBLREF int dollar_truth;
+GBLREF bool out_of_time;
+GBLREF volatile int4 outofband;
+
+error_def(ERR_CONNSOCKREQ);
+error_def(ERR_CREDNOTPASSED);
+error_def(ERR_CURRSOCKOFR);
+error_def(ERR_EXPR);
+error_def(ERR_LOCALSOCKREQ);
+error_def(ERR_NOSOCKETINDEV);
+error_def(ERR_NOSOCKHANDLE);
+error_def(ERR_PEERPIDMISMATCH);
+error_def(ERR_SOCKMAX);
+error_def(ERR_SOCKACCEPT);
+error_def(ERR_SOCKNOTFND);
+error_def(ERR_SOCKNOTPASSED);
+error_def(ERR_SOCKPASS);
+error_def(ERR_SOCKPASSDATAMIX);
+error_def(ERR_TEXT);
+error_def(ERR_ZINTRECURSEIO);
+
+pid_t get_peer_pid(int fd);
+
+struct msgdata
+{
+ int magic;
+ unsigned int proto_version;
+ int fdcount;
+};
+
+#define MSG_MAGIC 1431655765
+#define MSG_PROTO_VERSION 1
+
+void iosocket_pass_local(io_desc *iod, pid_t pid, int4 timeout, int argcnt, va_list args)
+{
+ d_socket_struct *dsocketptr;
+ socket_struct *socketptr, *psocketptr;
+ int argn, index, rval, save_errno;
+ mval *handle;
+ mstr handlestr;
+ mstr handles[MAX_PASS_FDS];
+ char cmsg_buffer[SIZEOF(struct cmsghdr) * 2 + CMSG_SPACE(MAX_PASS_FDS * SIZEOF(int))];
+ int4 cmsg_buflen;
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct msgdata mdata;
+ int *fds;
+ pid_t peerpid;
+ TID timer_id;
+ int4 msec_timeout;
+ char complete_buf[STR_LIT_LEN(ACCEPT_COMPLETE)];
+ char *errptr;
+ int4 errlen;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ if (1 > argcnt)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_NOSOCKHANDLE, 0);
+ return;
+ }
+ assert(gtmsocket == iod->type);
+ dsocketptr = (d_socket_struct *)iod->dev_sp;
+ if (0 >= dsocketptr->n_socket)
+ {
+ if (iod != io_std_device.out)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
+ return;
+ }
+ if (dsocketptr->n_socket <= dsocketptr->current_socket)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CURRSOCKOFR, 2, dsocketptr->current_socket, dsocketptr->n_socket);
+ return;
+ }
+ if (dsocketptr->mupintr)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO);
+ socketptr = dsocketptr->socket[dsocketptr->current_socket];
+ if (socket_local != socketptr->protocol)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_LOCALSOCKREQ, 0);
+ return;
+ }
+ if (socket_connected != socketptr->state)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_CONNSOCKREQ, 0);
+ return;
+ }
+ ENSURE_PASS_SOCKET(socketptr);
+ out_of_time = FALSE;
+# if PID_CHECKING_SUPPORTED
+ if (-1 != pid)
+ {
+ peerpid = get_peer_pid(socketptr->sd);
+ if (-1 == peerpid)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_CREDNOTPASSED, 0);
+ return;
+ }
+ if (pid != peerpid)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PEERPIDMISMATCH, 2, peerpid, pid);
+ return;
+ }
+ }
+# endif
+
+ /* pass fds */
+ fds = (int *)CMSG_DATA((struct cmsghdr *)cmsg_buffer);
+
+ for (argn=0; argn < argcnt; argn++)
+ {
+ handle = va_arg(args, mval *);
+ if ((NULL == handle) || !MV_DEFINED(handle))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_EXPR, 0);
+ return;
+ }
+ MV_FORCE_STR(handle);
+ if ((NULL == socket_pool)
+ || (0 > (index = iosocket_handle(handle->str.addr, &handle->str.len, FALSE, socket_pool))))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKNOTFND, 2, handle->str.len, handle->str.addr);
+ return;
+ }
+ handles[argn] = handle->str;
+ psocketptr = socket_pool->socket[index];
+ fds[argn] = psocketptr->sd;
+ }
+
+ /* send argcnt with fds */
+ mdata.magic = MSG_MAGIC;
+ mdata.proto_version = MSG_PROTO_VERSION;
+ mdata.fdcount = argcnt;
+ iov.iov_base = &mdata;
+ iov.iov_len = SIZEOF(mdata);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_control = (struct cmsghdr *)cmsg_buffer;
+ msg.msg_controllen = CMSG_SPACE(argcnt * SIZEOF(int));
+ cmsg = CMSG_FIRSTHDR(&msg);
+ assert(cmsg);
+ cmsg->cmsg_len = CMSG_LEN(argcnt * SIZEOF(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+
+ memcpy(iod->dollar.device, "0", SIZEOF("0"));
+
+ if (NO_M_TIMEOUT != timeout)
+ {
+ timer_id = (TID)iosocket_pass_local;
+ msec_timeout = timeout2msec(timeout);
+ start_timer(timer_id, msec_timeout, wake_alarm, 0, NULL);
+ }
+
+ do
+ {
+ rval = sendmsg(socketptr->sd, &msg, 0);
+ }
+ while (!outofband && !out_of_time && (-1 == rval) && (EINTR == errno));
+
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == iov.iov_len);
+
+ for (argn=0; argn < argcnt; argn++)
+ {
+ if (0 > (index = iosocket_handle(handles[argn].addr, &handles[argn].len, FALSE, socket_pool)))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKNOTFND, 2, handle->str.len, handle->str.addr);
+ return;
+ }
+ psocketptr = socket_pool->socket[index];
+
+ /* send handle length */
+ SENDALL(socketptr->sd, &handles[argn].len, SIZEOF(handles[argn].len), rval);
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == SIZEOF(handles[argn].len));
+
+ /* send handle */
+ SENDALL(socketptr->sd, handles[argn].addr, handles[argn].len, rval);
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == handles[argn].len);
+
+ /* send buffer length */
+ SENDALL(socketptr->sd, &psocketptr->buffered_length, SIZEOF(psocketptr->buffered_length), rval);
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == SIZEOF(psocketptr->buffered_length));
+
+ /* send buffer */
+ SENDALL(socketptr->sd, psocketptr->buffer + psocketptr->buffered_offset, psocketptr->buffered_length, rval);
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == psocketptr->buffered_length);
+ }
+ SENDALL(socketptr->sd, PASS_COMPLETE, STR_LIT_LEN(PASS_COMPLETE), rval);
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == STR_LIT_LEN(PASS_COMPLETE));
+ RECVALL(socketptr->sd, complete_buf, STR_LIT_LEN(ACCEPT_COMPLETE), rval);
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == STR_LIT_LEN(ACCEPT_COMPLETE));
+ if (0 != STRNCMP_LIT(complete_buf, ACCEPT_COMPLETE))
+ {
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+ iod->dollar.za = 9;
+ errptr = PROTOCOL_ERROR;
+ errlen = STR_LIT_LEN(PROTOCOL_ERROR);
+ MEMCPY_LIT(iod->dollar.device, DOLLAR_DEVICE_PREFIX);
+ memcpy(&iod->dollar.device[STR_LIT_LEN(DOLLAR_DEVICE_PREFIX)], errptr, errlen + 1); /* we want the null */
+ if (socketptr->ioerror)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKPASS, 0, ERR_TEXT, 2, errlen, errptr);
+ return;
+ }
+
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+
+ for (argn=0; argn < argcnt; argn++)
+ {
+ handlestr = handles[argn];
+ if (-1 != (index = iosocket_handle(handlestr.addr, &handlestr.len, FALSE, socket_pool)))
+ iosocket_close_one(socket_pool, index);
+ }
+
+ if (NO_M_TIMEOUT != timeout)
+ dollar_truth = TRUE;
+ return;
+
+ioerr:
+ save_errno = errno;
+ if (out_of_time && (EINTR == save_errno))
+ {
+ dollar_truth = FALSE;
+ return;
+ }
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+ iod->dollar.za = 9;
+ errptr = (char *)STRERROR(save_errno);
+ errlen = strlen(errptr);
+ MEMCPY_LIT(iod->dollar.device, DOLLAR_DEVICE_PREFIX);
+ memcpy(&iod->dollar.device[STR_LIT_LEN(DOLLAR_DEVICE_PREFIX)], errptr, errlen + 1); /* we want the null */
+ if (socketptr->ioerror)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKPASS, 0, save_errno, 0);
+ return;
+}
+
+void iosocket_accept_local(io_desc *iod, mval *handlesvar, pid_t pid, int4 timeout, int argcnt, va_list args)
+{
+ d_socket_struct *dsocketptr;
+ socket_struct *socketptr, *psocketptr;
+ int argn, index, fdcount = 0, fdn, scnt = 0, rval, save_errno, handleslen = 0;
+ mval *handle, tmp;
+ mstr handles[MAX_PASS_FDS];
+ mstr handlestr;
+ char cmsg_buffer[SIZEOF(struct cmsghdr) * 2 + CMSG_SPACE(MAX_PASS_FDS * SIZEOF(int))];
+ int4 cmsg_buflen;
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsg = NULL;
+ struct msgdata mdata;
+ int *fds;
+ char *hptr;
+ int handlelen;
+ size_t tmpbuflen;
+ pid_t peerpid;
+ TID timer_id;
+ int4 msec_timeout;
+ char complete_buf[STR_LIT_LEN(PASS_COMPLETE)];
+ char *errptr;
+ int4 errlen;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ assert(gtmsocket == iod->type);
+ dsocketptr = (d_socket_struct *)iod->dev_sp;
+ if (0 >= dsocketptr->n_socket)
+ {
+ if (iod != io_std_device.out)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
+ return;
+ }
+ if (dsocketptr->n_socket <= dsocketptr->current_socket)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CURRSOCKOFR, 2, dsocketptr->current_socket, dsocketptr->n_socket);
+ return;
+ }
+ if (dsocketptr->mupintr)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO);
+ socketptr = dsocketptr->socket[dsocketptr->current_socket];
+ if (socket_local != socketptr->protocol)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_LOCALSOCKREQ, 0);
+ return;
+ }
+ if (socket_connected != socketptr->state)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_CONNSOCKREQ, 0);
+ return;
+ }
+ ENSURE_PASS_SOCKET(socketptr);
+ out_of_time = FALSE;
+
+# if PID_CHECKING_SUPPORTED
+ if (-1 != pid)
+ {
+ peerpid = get_peer_pid(socketptr->sd);
+ if (-1 == peerpid)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_CREDNOTPASSED, 0);
+ return;
+ }
+ if (pid != peerpid)
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PEERPIDMISMATCH, 2, peerpid, pid);
+ return;
+ }
+ }
+# endif
+
+ /* accept fds */
+ if (NULL == socket_pool)
+ iosocket_poolinit();
+
+ for (argn=0; argn < argcnt; argn++)
+ {
+ handle = va_arg(args, mval *);
+ if ((NULL != handle) && MV_DEFINED(handle))
+ MV_FORCE_STR(handle);
+ if ((NULL == handle) || !MV_DEFINED(handle)
+ || (-1 != iosocket_handle(handle->str.addr, &handle->str.len, FALSE, socket_pool)))
+ handles[argn].addr = NULL; /* use passed or generated handle */
+ else
+ handles[argn] = handle->str;
+ }
+
+ memcpy(iod->dollar.device, "0", SIZEOF("0"));
+
+ if (NO_M_TIMEOUT != timeout)
+ {
+ timer_id = (TID)iosocket_accept_local;
+ msec_timeout = timeout2msec(timeout);
+ start_timer(timer_id, msec_timeout, wake_alarm, 0, NULL);
+ }
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ /* read fd count first */
+ iov.iov_base = &mdata;
+ iov.iov_len = SIZEOF(mdata);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = (struct cmsghdr *)cmsg_buffer;
+ msg.msg_controllen = CMSG_SPACE(MAX_PASS_FDS * SIZEOF(int));
+
+ do
+ {
+ rval = recvmsg(socketptr->sd, &msg, 0);
+ }
+ while (!outofband && !out_of_time && (-1 == rval) && (EINTR == errno));
+
+ if (0 == rval)
+ {
+ rval = -1;
+ errno = ECONNRESET;
+ }
+ if (-1 == rval)
+ goto ioerr;
+ if (SIZEOF(mdata) != rval)
+ {
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_SOCKNOTPASSED, 0);
+ return;
+ }
+ assert(rval == iov.iov_len);
+
+ if ((MSG_MAGIC != mdata.magic) || (MSG_PROTO_VERSION != mdata.proto_version))
+ {
+ iod->dollar.za = 9;
+ errptr = PROTOCOL_ERROR;
+ errlen = STR_LIT_LEN(PROTOCOL_ERROR);
+ MEMCPY_LIT(iod->dollar.device, DOLLAR_DEVICE_PREFIX);
+ memcpy(&iod->dollar.device[STR_LIT_LEN(DOLLAR_DEVICE_PREFIX)], errptr, errlen + 1); /* we want the null */
+ if (socketptr->ioerror)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKACCEPT, 0, ERR_TEXT, 2, errlen, errptr);
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ while((cmsg != NULL) && ((SOL_SOCKET != cmsg->cmsg_level) || (SCM_RIGHTS != cmsg->cmsg_type)))
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+
+ if (NULL == cmsg)
+ {
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_SOCKNOTPASSED, 0);
+ return;
+ }
+
+ fdcount = mdata.fdcount;
+ fds = (int *)CMSG_DATA(cmsg);
+ assert(((cmsg->cmsg_len - ((char *)CMSG_DATA(cmsg) - (char *)cmsg)) / SIZEOF(int)) == fdcount);
+
+ if (0 == fdcount)
+ {
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2) ERR_SOCKNOTPASSED, 0);
+ return;
+ }
+
+ if (gtm_max_sockets <= (socket_pool->n_socket + fdcount))
+ {
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+ for (fdn = 0; fdn < fdcount; fdn++)
+ {
+ CLOSE(fds[fdn], rval);
+ }
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
+ return;
+ }
+
+ for (fdn=0; fdn < fdcount; fdn++)
+ {
+ /* read handle length */
+ RECVALL(socketptr->sd, &handlestr.len, SIZEOF(handlestr.len), rval);
+ if (-1 == rval)
+ goto ioerr;
+ assertpro(SIZEOF(handlestr.len) == rval);
+
+ /* read handle */
+ ENSURE_STP_FREE_SPACE(MAX_HANDLE_LEN);
+ handlestr.addr = (char *)stringpool.free;
+
+ RECVALL(socketptr->sd, handlestr.addr, handlestr.len, rval);
+ if (-1 == rval)
+ goto ioerr;
+ assertpro(handlestr.len == rval);
+
+ if ((fdn >= argcnt) || (NULL == handles[fdn].addr))
+ {
+ /* If the passed handle name already exists in the socket pool, create a new one */
+ if (-1 != iosocket_handle(handlestr.addr, &handlestr.len, FALSE, socket_pool))
+ iosocket_handle(handlestr.addr, &handlestr.len, TRUE, socket_pool);
+ stringpool.free += handlestr.len;
+ handles[fdn] = handlestr;
+ }
+ else
+ handlestr = handles[fdn]; /* Use the handle from the argument list */
+
+ /* read socket buffer length */
+ RECVALL(socketptr->sd, &tmpbuflen, SIZEOF(tmpbuflen), rval);
+ if (-1 == rval)
+ goto ioerr;
+ assertpro(SIZEOF(tmpbuflen) == rval);
+
+ psocketptr = iosocket_create(NULL,
+ ((tmpbuflen > DEFAULT_SOCKET_BUFFER_SIZE) ? tmpbuflen : DEFAULT_SOCKET_BUFFER_SIZE),
+ fds[fdn], FALSE);
+ assertpro(NULL != psocketptr);
+ psocketptr->handle_len = handlestr.len;
+ memcpy(psocketptr->handle, handlestr.addr, handlestr.len);
+ psocketptr->dev = socket_pool;
+ socket_pool->socket[socket_pool->n_socket++] = psocketptr;
+ socket_pool->current_socket = socket_pool->n_socket - 1;
+ scnt++;
+
+ if (0 < tmpbuflen)
+ {
+ /* read socket buffer */
+ psocketptr->buffered_length = tmpbuflen;
+ RECVALL(socketptr->sd, psocketptr->buffer, psocketptr->buffered_length, rval);
+ if (-1 == rval)
+ goto ioerr;
+ assertpro(psocketptr->buffered_length == rval);
+ }
+ psocketptr->buffered_offset = 0;
+
+ handleslen += handlestr.len;
+ }
+ RECVALL(socketptr->sd, complete_buf, STR_LIT_LEN(PASS_COMPLETE), rval);
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == STR_LIT_LEN(PASS_COMPLETE));
+ if (0 != STRNCMP_LIT(complete_buf, PASS_COMPLETE))
+ {
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+ for (fdn = scnt - 1; fdn >= 0; fdn--)
+ {
+ if (-1 != (index = iosocket_handle(handles[fdn].addr, &handles[fdn].len, FALSE, socket_pool)))
+ iosocket_close_one(socket_pool, index);
+ }
+ for (fdn = scnt; fdn < fdcount; fdn++)
+ {
+ CLOSE(fds[fdn], rval);
+ }
+ iod->dollar.za = 9;
+ errptr = PROTOCOL_ERROR;
+ errlen = STR_LIT_LEN(PROTOCOL_ERROR);
+ MEMCPY_LIT(iod->dollar.device, DOLLAR_DEVICE_PREFIX);
+ memcpy(&iod->dollar.device[STR_LIT_LEN(DOLLAR_DEVICE_PREFIX)], errptr, errlen + 1); /* we want the null */
+ if (socketptr->ioerror)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKACCEPT, 0, ERR_TEXT, 2, errlen, errptr);
+ return;
+ }
+ SENDALL(socketptr->sd, ACCEPT_COMPLETE, STR_LIT_LEN(ACCEPT_COMPLETE), rval);
+ if (-1 == rval)
+ goto ioerr;
+ assert(rval == STR_LIT_LEN(ACCEPT_COMPLETE));
+
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+
+ if (NULL != handlesvar)
+ {
+ handleslen += (fdcount > 1) ? (fdcount - 1) : 0; /* space for delimiters */
+ ENSURE_STP_FREE_SPACE(handleslen);
+ hptr = (char *)stringpool.free;
+ stringpool.free += handleslen;
+ handlesvar->mvtype = MV_STR;
+ handlesvar->str.addr = hptr;
+ handlesvar->str.len = handleslen;
+
+ memcpy(hptr, handles[0].addr, handles[0].len);
+ hptr += handles[0].len;
+
+ for (fdn=1; fdn < fdcount; fdn++)
+ {
+ *hptr++ = '|';
+ memcpy(hptr, handles[fdn].addr, handles[fdn].len);
+ hptr += handles[fdn].len;
+ }
+ }
+
+ if (NO_M_TIMEOUT != timeout)
+ dollar_truth = TRUE;
+ return;
+
+ioerr:
+ save_errno = errno;
+ if (out_of_time && (EINTR == save_errno))
+ {
+ dollar_truth = FALSE;
+ }
+ if ((NO_M_TIMEOUT != timeout) && !out_of_time)
+ cancel_timer(timer_id);
+ for (fdn = scnt - 1; fdn >= 0; fdn--)
+ {
+ if (-1 != (index = iosocket_handle(handles[fdn].addr, &handles[fdn].len, FALSE, socket_pool)))
+ iosocket_close_one(socket_pool, index);
+ }
+ for (fdn = scnt; fdn < fdcount; fdn++)
+ {
+ CLOSE(fds[fdn], rval);
+ }
+ if ((EINTR != save_errno) || outofband)
+ {
+ iod->dollar.za = 9;
+ errptr = (char *)STRERROR(save_errno);
+ errlen = strlen(errptr);
+ MEMCPY_LIT(iod->dollar.device, DOLLAR_DEVICE_PREFIX);
+ memcpy(&iod->dollar.device[STR_LIT_LEN(DOLLAR_DEVICE_PREFIX)], errptr, errlen + 1); /* we want the null */
+ if (socketptr->ioerror)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKACCEPT, 0, save_errno, 0);
+ }
+ return;
+}
+
+pid_t get_peer_pid(int fd)
+{
+# if defined(__linux__)
+ struct ucred creds;
+ GTM_SOCKLEN_TYPE solen;
+
+ solen = SIZEOF(struct ucred);
+ if (-1 == getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &solen))
+ return -1;
+ else
+ return creds.pid;
+# elif defined(_AIX)
+ struct peercred_struct creds;
+ GTM_SOCKLEN_TYPE solen;
+
+ solen = SIZEOF(struct peercred_struct);
+ if (-1 == getsockopt(fd, SOL_SOCKET, SO_PEERID, &creds, &solen))
+ return -1;
+ else
+ return creds.pid;
+# elif defined(__sun)
+ ucred_t *credsptr = NULL;
+ pid_t peerpid;
+
+ if (-1 == getpeerucred(fd, &credsptr))
+ return -1;
+ else
+ {
+ peerpid = ucred_getpid(credsptr);
+ ucred_free(credsptr);
+ return peerpid;
+ }
+# else
+ return -1;
+# endif
+}
diff --git a/sr_unix/iott_edit.c b/sr_unix/iott_edit.c
index 9cc8b41..eafc4b3 100644
--- a/sr_unix/iott_edit.c
+++ b/sr_unix/iott_edit.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2005, 2009 Fidelity Information Services, Inc *
+ * Copyright 2005, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -245,20 +245,15 @@ int write_str(void *str832, unsigned int len, unsigned int start_x, boolean_t m
number_of_chars_left = cur_x - start_x;
if (!move)
{
- ret = write_loop(fildes, (unsigned char *)CURSOR_UP, number_of_lines_up);
+ ret = (NULL != CURSOR_UP) ? write_loop(fildes, (unsigned char *)CURSOR_UP, number_of_lines_up) : 0;
if (0 > ret)
return -1;
if (number_of_chars_left > 0)
- {
- ret = write_loop(fildes, (unsigned char *)CURSOR_LEFT, number_of_chars_left);
- if (0 > ret)
- return -1;
- } else
- {
- ret = write_loop(fildes, (unsigned char *)CURSOR_RIGHT, -number_of_chars_left);
- if (0 > ret)
- return -1;
- }
+ ret = (NULL != CURSOR_LEFT) ? write_loop(fildes, (unsigned char *)CURSOR_LEFT, number_of_chars_left) : 0;
+ else
+ ret = (NULL != CURSOR_RIGHT) ? write_loop(fildes, (unsigned char *)CURSOR_RIGHT, -number_of_chars_left) : 0;
+ if (0 > ret)
+ return -1;
}
return 0;
}
@@ -303,21 +298,29 @@ int move_cursor_left(int col, int num_cols)
ret = move_cursor_right(col, -num_cols);
else if (0 < col)
{
- ret = write_loop(fildes, (unsigned char *)CURSOR_LEFT, MIN(col, num_cols));
+ ret = (NULL != CURSOR_LEFT) ? write_loop(fildes, (unsigned char *)CURSOR_LEFT, MIN(col, num_cols)) : 0;
num_cols -= MIN(col, num_cols);
if (num_cols)
{
+ if (NULL != CURSOR_UP)
+ {
+ DOWRITERC(fildes, CURSOR_UP, strlen(CURSOR_UP), ret);
+ if (0 > ret)
+ return -1;
+ }
+ ret = (NULL != CURSOR_RIGHT)
+ ? write_loop(fildes, (unsigned char *)CURSOR_RIGHT, io_curr_device.in->width - num_cols) : 0;
+ }
+ } else
+ {
+ if (NULL != CURSOR_UP)
+ {
DOWRITERC(fildes, CURSOR_UP, strlen(CURSOR_UP), ret);
if (0 > ret)
return -1;
- ret = write_loop(fildes, (unsigned char *)CURSOR_RIGHT, io_curr_device.in->width - num_cols);
}
- } else
- {
- DOWRITERC(fildes, CURSOR_UP, strlen(CURSOR_UP), ret);
- if (0 > ret)
- return -1;
- ret = write_loop(fildes, (unsigned char *)CURSOR_RIGHT, io_curr_device.in->width - num_cols);
+ ret = (NULL != CURSOR_RIGHT)
+ ? write_loop(fildes, (unsigned char *)CURSOR_RIGHT, io_curr_device.in->width - num_cols) : 0;
}
return ret;
}
@@ -339,7 +342,7 @@ int move_cursor_right(int col, int num_cols)
else if (0 > num_cols)
ret = move_cursor_left(col, -num_cols);
else if ((io_curr_device.in->width - num_cols) > col)
- ret = write_loop(fildes, (unsigned char *)CURSOR_RIGHT, num_cols);
+ ret = (NULL != CURSOR_RIGHT) ? write_loop(fildes, (unsigned char *)CURSOR_RIGHT, num_cols) : 0;
else
{
DOWRITERC(fildes, NATIVE_TTEOL, strlen(NATIVE_TTEOL), ret);
@@ -347,7 +350,7 @@ int move_cursor_right(int col, int num_cols)
return -1;
num_cols -= (io_curr_device.in->width - col);
if (num_cols)
- ret = write_loop(fildes, (unsigned char *)CURSOR_RIGHT, num_cols);
+ ret = (NULL != CURSOR_RIGHT) ? write_loop(fildes, (unsigned char *)CURSOR_RIGHT, num_cols) : 0;
}
return ret;
}
@@ -386,29 +389,21 @@ int move_cursor(int fildes, int num_up, int num_left)
{
int ret;
- if (num_up < 0)
- {
+ ret = 0;
+ if ((num_up < 0) && (NULL != CURSOR_DOWN))
ret = write_loop (fildes, (unsigned char *)CURSOR_DOWN, -num_up);
- if (0 > ret)
- return -1;
- } else if (num_up > 0)
- {
+ else if ((num_up > 0) && (NULL != CURSOR_UP))
ret = write_loop (fildes, (unsigned char *)CURSOR_UP, num_up);
- if (0 > ret)
- return -1;
- }
+ if (0 > ret)
+ return -1;
- if (num_left < 0)
- {
+ ret = 0;
+ if ((num_left < 0) && (NULL != CURSOR_RIGHT))
ret = write_loop(fildes, (unsigned char *)CURSOR_RIGHT, -num_left);
- if (0 > ret)
- return -1;
- } else if (num_left > 0)
- {
+ else if ((num_left > 0) && (NULL != CURSOR_LEFT))
ret = write_loop(fildes, (unsigned char *)CURSOR_LEFT, num_left);
- if (0 > ret)
- return -1;
- }
+ if (0 > ret)
+ return -1;
return 0;
}
diff --git a/sr_unix/iott_iocontrol.c b/sr_unix/iott_iocontrol.c
index 06eb394..2f5bd4a 100644
--- a/sr_unix/iott_iocontrol.c
+++ b/sr_unix/iott_iocontrol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,7 +19,7 @@
GBLREF io_pair io_curr_device;
-void iott_iocontrol(mstr *d)
+void iott_iocontrol(mstr *mn, int4 argcnt, va_list args)
{
return;
}
@@ -29,7 +29,7 @@ void iott_dlr_device(mstr *d)
io_desc *iod;
int len;
- iod = io_curr_device.out;
+ iod = io_curr_device.in;
len = STRLEN(iod->dollar.device);
/* verify internal buffer has enough space for $DEVICE string value */
assert((int)d->len > len);
@@ -43,7 +43,7 @@ void iott_dlr_key(mstr *d)
io_desc *iod;
int len;
- iod = io_curr_device.out;
+ iod = io_curr_device.in;
len = STRLEN(iod->dollar.key);
/* verify internal buffer has enough space for $KEY string value */
assert((int)d->len > len);
diff --git a/sr_unix/iott_readfl.c b/sr_unix/iott_readfl.c
index 34356a9..d9661f4 100644
--- a/sr_unix/iott_readfl.c
+++ b/sr_unix/iott_readfl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -59,7 +59,6 @@ LITREF UChar32 u32_line_term[];
#endif
GBLREF int AUTO_RIGHT_MARGIN, EAT_NEWLINE_GLITCH;
-GBLREF char *CURSOR_UP, *CURSOR_DOWN, *CURSOR_LEFT, *CURSOR_RIGHT, *CLR_EOL;
GBLREF char *KEY_BACKSPACE, *KEY_DC;
GBLREF char *KEY_DOWN, *KEY_LEFT, *KEY_RIGHT, *KEY_UP;
GBLREF char *KEY_INSERT;
@@ -581,8 +580,9 @@ int iott_readfl(mval *v, int4 length, int4 timeout) /* timeout in seconds */
/* For most of the terminal the 'kbs' string capability is a byte in length. It means that it is
Not treated as escape sequence. So explicitly check if the input corresponds to the 'kbs' */
if ((((int)inchar == tt_ptr->ttio_struct->c_cc[VERASE]) ||
- (empterm && ('\0' == KEY_BACKSPACE[1]) && (inchar == KEY_BACKSPACE[0])))
- && !(mask & TRM_PASTHRU))
+ (empterm && (NULL != KEY_BACKSPACE) && ('\0' == KEY_BACKSPACE[1])
+ && (inchar == KEY_BACKSPACE[0])))
+ && !(mask & TRM_PASTHRU))
{
if (0 < instr && (edit_mode || 0 < dx))
{
@@ -963,23 +963,20 @@ int iott_readfl(mval *v, int4 length, int4 timeout) /* timeout in seconds */
int zb_len = (int)(zb_ptr - io_ptr->dollar.zb);
escape_edit = FALSE;
- down = strncmp((const char *)io_ptr->dollar.zb, KEY_DOWN, zb_len);
- up = strncmp((const char *)io_ptr->dollar.zb, KEY_UP, zb_len);
- right = strncmp((const char *)io_ptr->dollar.zb, KEY_RIGHT, zb_len);
- left = strncmp((const char *)io_ptr->dollar.zb, KEY_LEFT, zb_len);
- backspace = delete = insert_key = -1;
+ /* The arbitrary value -1 signifies inequality in case KEY_* is NULL */
+ down = (NULL != KEY_DOWN) ? strncmp((const char *)io_ptr->dollar.zb, KEY_DOWN, zb_len) : -1;
+ up = (NULL != KEY_UP) ? strncmp((const char *)io_ptr->dollar.zb, KEY_UP, zb_len) : -1;
+ right = (NULL != KEY_RIGHT) ? strncmp((const char *)io_ptr->dollar.zb, KEY_RIGHT, zb_len) : -1;
+ left = (NULL != KEY_LEFT) ? strncmp((const char *)io_ptr->dollar.zb, KEY_LEFT, zb_len) : -1;
+ backspace = (KEY_BACKSPACE != NULL) ? strncmp((const char *)io_ptr->dollar.zb, KEY_BACKSPACE, zb_len) : -1;
+ delete = (KEY_DC != NULL) ? strncmp((const char *)io_ptr->dollar.zb, KEY_DC, zb_len) : -1;
+ insert_key = (KEY_INSERT != NULL && '\0' != KEY_INSERT[0])
+ ? strncmp((const char *)io_ptr->dollar.zb, KEY_INSERT, zb_len) : -1;
- if (KEY_BACKSPACE != NULL)
- backspace = strncmp((const char *)io_ptr->dollar.zb, KEY_BACKSPACE, zb_len);
- if (KEY_DC != NULL)
- delete = strncmp((const char *)io_ptr->dollar.zb, KEY_DC, zb_len);
- if (KEY_INSERT != NULL && '\0' != KEY_INSERT[0])
- insert_key = strncmp((const char *)io_ptr->dollar.zb, KEY_INSERT, zb_len);
-
- if (backspace == 0 || delete == 0)
+ if (0 == backspace || 0 == delete)
{
- if (instr > 0)
- {
+ if ((0 == backspace) && (instr > 0))
+ { /* Move one character to the left */
dx_prev = compute_dx(BUFF_ADDR(0), instr - 1, ioptr_width, dx_start);
delchar_width = dx_instr - dx_prev;
if (!(mask & TRM_NOECHO))
@@ -990,6 +987,9 @@ int iott_readfl(mval *v, int4 length, int4 timeout) /* timeout in seconds */
dx = (dx - delchar_width + ioptr_width) % ioptr_width;
instr--;
dx_instr -= delchar_width;
+ }
+ if (instr != outlen)
+ {
STORE_OFF(' ', outlen);
outlen--;
if (!(mask & TRM_NOECHO))
diff --git a/sr_unix/iott_use.c b/sr_unix/iott_use.c
index a8ce829..3343586 100644
--- a/sr_unix/iott_use.c
+++ b/sr_unix/iott_use.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -35,6 +35,7 @@
#include "error.h"
#include "gtm_tputs.h"
#include "gtm_tparm.h"
+#include "outofband.h"
LITDEF nametabent filter_names[] =
{
@@ -50,13 +51,12 @@ LITDEF unsigned char filter_index[27] =
,4, 4, 4
};
-GBLREF bool ctrlc_on;
-GBLREF char *CURSOR_ADDRESS, *CLR_EOL, *CLR_EOS;
-GBLREF io_pair io_std_device;
-GBLREF io_pair io_curr_device;
-GBLREF bool prin_out_dev_failure;
-GBLREF void (*ctrlc_handler_ptr)();
-GBLREF boolean_t dollar_zininterrupt;
+GBLREF boolean_t ctrlc_on, dollar_zininterrupt;
+GBLREF bool prin_out_dev_failure;
+GBLREF char *CURSOR_ADDRESS, *CLR_EOL, *CLR_EOS;
+GBLREF io_pair io_std_device;
+GBLREF io_pair io_curr_device;
+GBLREF void (*ctrlc_handler_ptr)();
LITREF unsigned char io_params_size[];
@@ -71,20 +71,17 @@ error_def(ERR_ZINTRECURSEIO);
void iott_use(io_desc *iod, mval *pp)
{
- boolean_t flush_input;
- char dc1;
- int fil_type;
- unsigned char ch, len;
- int4 length, width;
- uint4 mask_in;
- d_tt_struct *temp_ptr, *tt_ptr;
- io_desc *d_in, *d_out;
- io_termmask mask_term;
- char *ttab;
- struct termios t;
- int status;
- int save_errno;
- int p_offset;
+ boolean_t flush_input;
+ char dc1, *ttab;
+ d_tt_struct *temp_ptr, *tt_ptr;
+ int p_offset, fil_type, save_errno, status;
+ int4 length, width;
+ io_desc *d_in, *d_out;
+ io_termmask mask_term;
+ struct sigaction act;
+ struct termios t;
+ uint4 mask_in;
+ unsigned char ch, len;
p_offset = 0;
assert(iod->state == dev_open);
@@ -106,16 +103,16 @@ void iott_use(io_desc *iod, mval *pp)
{
save_errno = errno;
if (io_curr_device.out == io_std_device.out)
- {
- if (!prin_out_dev_failure)
- prin_out_dev_failure = TRUE;
- else
- {
- send_msg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOPRINCIO);
- stop_image_no_core();
- }
- }
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TCGETATTR, 1, tt_ptr->fildes, save_errno);
+ {
+ if (!prin_out_dev_failure)
+ prin_out_dev_failure = TRUE;
+ else
+ {
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOPRINCIO);
+ stop_image_no_core();
+ }
+ }
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TCGETATTR, 1, tt_ptr->fildes, save_errno);
}
flush_input = FALSE;
d_in = iod->pair.in;
@@ -142,33 +139,39 @@ void iott_use(io_desc *iod, mval *pp)
tt_ptr->ext_cap &= ~TT_EMPTERM;
break;
case iop_cenable:
- temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
- if (tt_ptr->fildes == temp_ptr->fildes && !ctrlc_on)
- {
- struct sigaction act;
-
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = ctrlc_handler_ptr;
- sigaction(SIGINT, &act, 0);
- ctrlc_on = TRUE;
+ if (!ctrlc_on)
+ { /* if it's already cenable, no need to change */
+ temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
+ if (tt_ptr->fildes == temp_ptr->fildes)
+ { /* if this is $PRINCIPAL make sure the ctrlc_handler is enabled */
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = ctrlc_handler_ptr;
+ sigaction(SIGINT, &act, 0);
+ ctrlc_on = TRUE;
+ }
}
break;
case iop_nocenable:
- temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
- if (tt_ptr->fildes == temp_ptr->fildes && ctrlc_on)
- {
- struct sigaction act;
-
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = SIG_IGN;
- sigaction(SIGINT, &act, 0);
- ctrlc_on = FALSE;
+ if (ctrlc_on)
+ { /* if it's already nocenable, no need to change */
+ temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
+ if (tt_ptr->fildes == temp_ptr->fildes)
+ { /* if this is $PRINCIPAL may disable the ctrlc_handler */
+ if (0 == (CTRLC_MSK & tt_ptr->enbld_outofbands.mask))
+ { /* but only if ctrap=$c(3) is not active */
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &act, 0);
+ }
+ ctrlc_on = FALSE;
+ }
}
break;
case iop_clearscreen:
- gtm_tputs(CLR_EOS, 1, outc);
+ if (NULL != CLR_EOS)
+ gtm_tputs(CLR_EOS, 1, outc);
break;
case iop_convert:
mask_in |= TRM_CONVERT;
@@ -178,12 +181,22 @@ void iott_use(io_desc *iod, mval *pp)
break;
case iop_ctrap:
GET_LONG(tt_ptr->enbld_outofbands.mask, pp->str.addr + p_offset);
+ if (!ctrlc_on)
+ { /* if cenable, ctrlc_handler active anyway, otherwise, depends on ctrap=$c(3) */
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = (CTRLC_MSK & tt_ptr->enbld_outofbands.mask)
+ ? ctrlc_handler_ptr : SIG_IGN;
+ sigaction(SIGINT, &act, 0);
+ }
break;
case iop_downscroll:
if (d_out->dollar.y > 0)
{
d_out->dollar.y--;
- gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
+ if (NULL != CURSOR_ADDRESS)
+ gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1,
+ outc);
}
break;
case iop_echo:
@@ -217,7 +230,8 @@ void iott_use(io_desc *iod, mval *pp)
default:
break;
case iop_eraseline:
- gtm_tputs(CLR_EOL, 1, outc);
+ if (NULL != CLR_EOL)
+ gtm_tputs(CLR_EOL, 1, outc);
break;
case iop_exception:
iod->error_handler.len = *(pp->str.addr + p_offset);
@@ -334,7 +348,8 @@ void iott_use(io_desc *iod, mval *pp)
d_out->dollar.y++;
if (d_out->length)
d_out->dollar.y %= d_out->length;
- gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
+ if (NULL != CURSOR_ADDRESS)
+ gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
break;
case iop_width:
GET_LONG(width, pp->str.addr + p_offset);
@@ -370,7 +385,8 @@ void iott_use(io_desc *iod, mval *pp)
d_out->dollar.y %= d_out->length;
d_out->dollar.x %= d_out->width;
}
- gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
+ if (NULL != CURSOR_ADDRESS)
+ gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
break;
case iop_y:
GET_LONG(d_out->dollar.y, pp->str.addr + p_offset);
@@ -378,11 +394,12 @@ void iott_use(io_desc *iod, mval *pp)
d_out->dollar.y = 0;
if (d_out->length)
d_out->dollar.y %= d_out->length;
- gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
+ if (NULL != CURSOR_ADDRESS)
+ gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
break;
case iop_ipchset:
{
-#ifdef KEEP_zOS_EBCDIC
+# ifdef KEEP_zOS_EBCDIC
if ( (iconv_t)0 != iod->input_conv_cd )
{
ICONV_CLOSE_CD(iod->input_conv_cd);
@@ -391,12 +408,12 @@ void iott_use(io_desc *iod, mval *pp)
if (DEFAULT_CODE_SET != iod->in_code_set)
ICONV_OPEN_CD(iod->input_conv_cd,
(char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
-#endif
- break;
+# endif
+ break;
}
- case iop_opchset:
+ case iop_opchset:
{
-#ifdef KEEP_zOS_EBCDIC
+# ifdef KEEP_zOS_EBCDIC
if ( (iconv_t)0 != iod->output_conv_cd)
{
ICONV_CLOSE_CD(iod->output_conv_cd);
@@ -405,8 +422,8 @@ void iott_use(io_desc *iod, mval *pp)
if (DEFAULT_CODE_SET != iod->out_code_set)
ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET,
(char *)(pp->str.addr + p_offset + 1));
-#endif
- break;
+# endif
+ break;
}
}
p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
diff --git a/sr_unix/ious_iocontrol.c b/sr_unix/ious_iocontrol.c
index 9b0a0bb..9e5f0eb 100644
--- a/sr_unix/ious_iocontrol.c
+++ b/sr_unix/ious_iocontrol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2004 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -15,7 +15,7 @@
GBLREF io_pair io_curr_device;
-void ious_iocontrol(mstr *d)
+void ious_iocontrol(mstr *mn, int4 argcnt, va_list args)
{
return;
}
diff --git a/sr_unix/is_file_identical.c b/sr_unix/is_file_identical.c
index d201ab0..93fd941 100644
--- a/sr_unix/is_file_identical.c
+++ b/sr_unix/is_file_identical.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -32,11 +32,12 @@
#include "eintr_wrappers.h"
#include "copy.h"
#include "is_file_identical.h"
+#include "iosp.h" /* for SS_NORMAL */
bool is_gdid_file_identical(gd_id_ptr_t fid, char *filename, int4 filelen)
{
- struct stat stat_buf;
int stat_res;
+ struct stat stat_buf;
assert(0 == filename[filelen]);
STAT_FILE(filename, &stat_buf, stat_res);
@@ -44,25 +45,25 @@ bool is_gdid_file_identical(gd_id_ptr_t fid, char *filename, int4 filelen)
}
bool is_file_identical(char *filename1, char *filename2)
{
- struct stat st1, st2;
- int stat_res;
int rv = FALSE;
+ int stat_res;
+ struct stat st1, st2;
STAT_FILE(filename1, &st1, stat_res);
if (0 == stat_res)
{
STAT_FILE(filename2, &st2, stat_res);
- if (0 == stat_res)
+ if (0 == stat_res)
#if defined(__osf__) || defined(_AIX)
if ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino) && (
#ifdef _AIX
- (FS_REMOTE == st1.st_flag || FS_REMOTE == st2.st_flag) ? TRUE :
+ (FS_REMOTE == st1.st_flag || FS_REMOTE == st2.st_flag) ? TRUE :
#endif
- st1.st_gen == st2.st_gen))
+ st1.st_gen == st2.st_gen))
#else
- if ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino))
+ if ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino))
#endif
- rv = TRUE;
+ rv = TRUE;
}
return rv;
}
@@ -70,6 +71,7 @@ bool is_file_identical(char *filename1, char *filename2)
bool is_gdid_identical(gd_id_ptr_t fid1, gd_id_ptr_t fid2)
{
bool rv = FALSE;
+
#if defined(__osf__) || defined(_AIX)
if ((fid1->inode == fid2->inode) && (fid1->device == fid2->device) && (fid1->st_gen == fid2->st_gen))
rv = TRUE;
@@ -80,11 +82,9 @@ bool is_gdid_identical(gd_id_ptr_t fid1, gd_id_ptr_t fid2)
return rv;
}
-
bool is_gdid_stat_identical(gd_id_ptr_t fid, struct stat *stat_buf)
{
#if defined(__osf__) || defined(_AIX)
-
assert(SIZEOF(fid->st_gen) >= SIZEOF(stat_buf->st_gen));
if (fid->device == stat_buf->st_dev && fid->inode == stat_buf->st_ino && (
#ifdef _AIX
@@ -117,14 +117,14 @@ void set_gdid_from_stat(gd_id_ptr_t fid, struct stat *stat_buf)
/*
* Here we create a unique_id for a file.
*/
-boolean_t filename_to_id(gd_id_ptr_t fid, char *filename)
+uint4 filename_to_id(gd_id_ptr_t fid, char *filename)
{
- struct stat filestat;
int stat_res;
+ struct stat filestat;
STAT_FILE(filename, &filestat, stat_res);
- if (stat_res)
- return FALSE;
+ if (-1 == stat_res)
+ return errno;
set_gdid_from_stat(fid, &filestat);
- return TRUE;
+ return SS_NORMAL;
}
diff --git a/sr_unix/jnl_file_extend.c b/sr_unix/jnl_file_extend.c
index 010bc38..414e841 100644
--- a/sr_unix/jnl_file_extend.c
+++ b/sr_unix/jnl_file_extend.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -103,7 +103,7 @@ uint4 jnl_file_extend(jnl_private_control *jpc, uint4 total_jnl_rec_size)
jb = jpc->jnl_buff;
assert(0 <= new_blocks);
DEBUG_ONLY(count = 0);
- for (need_extend = (0 != new_blocks); need_extend; )
+ for (need_extend = (jb->last_eof_written || (0 != new_blocks)); need_extend; )
{
DEBUG_ONLY(count++);
/* usually we will do the loop just once where we do the file extension.
@@ -151,7 +151,7 @@ uint4 jnl_file_extend(jnl_private_control *jpc, uint4 total_jnl_rec_size)
if (csd->autoswitchlimit < (jb->filesize + (EXTEND_WARNING_FACTOR * new_blocks))) /* close to max */
send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_JNLSPACELOW, 3, JNL_LEN_STR(csd),
csd->autoswitchlimit - jb->filesize);
- if (csd->autoswitchlimit < new_alq)
+ if (jb->last_eof_written || (csd->autoswitchlimit < new_alq))
{ /* Reached max, need to autoswitch */
/* Ensure new journal file can hold the entire current transaction's journal record requirements */
assert(csd->autoswitchlimit >= MAX_REQD_JNL_FILE_SIZE(total_jnl_rec_size));
@@ -160,8 +160,19 @@ uint4 jnl_file_extend(jnl_private_control *jpc, uint4 total_jnl_rec_size)
set_jnl_info(gv_cur_region, &jnl_info);
assert(JNL_ENABLED(csa) && (NOJNL != jpc->channel) && !(JNL_FILE_SWITCHED(jpc)));
jnl_status = jnl_ensure_open();
- if (0 == jnl_status)
- { /* flush the cache and jnl-buffer-contents to current journal file before
+ if (0 != jnl_status)
+ {
+ if (SS_NORMAL != jpc->status)
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(7) jnl_status, 4, JNL_LEN_STR(csd),
+ DB_LEN_STR(gv_cur_region), jpc->status);
+ else
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(csd),
+ DB_LEN_STR(gv_cur_region));
+ return EXIT_ERR;
+ }
+ if (!jb->last_eof_written)
+ {
+ /* flush the cache and jnl-buffer-contents to current journal file before
* switching to a new journal. Set a global variable in_jnl_file_autoswitch
* so jnl_write can know not to do the padding check. But because this is a global
* variable, we also need to make sure it is reset in case of errors during the
@@ -182,36 +193,30 @@ uint4 jnl_file_extend(jnl_private_control *jpc, uint4 total_jnl_rec_size)
* temporarily been modified in case of errors inside wcs_flu/jnl_file_close.
*/
ESTABLISH_RET(jnl_file_autoswitch_ch, EXIT_ERR);
- /* It is possible we still have not written a PINI record in this journal file
- * (e.g. mupip extend saw the need to do jnl_file_extend inside jnl_write while
- * trying to write a PINI record). Write a PINI record in that case before closing
- * the journal file that way the EOF record will have a non-zero pini_addr.
- */
- if (0 == jpc->pini_addr)
- jnl_put_jrt_pini(csa);
- wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SPEEDUP_NOBEFORE);
+ if (!wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SPEEDUP_NOBEFORE))
+ {
+ if (SS_NORMAL != jpc->status)
+ rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) jpc->status, 4, JNL_LEN_STR(csd),
+ DB_LEN_STR(gv_cur_region));
+ }
+ assert(in_jnl_file_autoswitch);
jnl_file_close(gv_cur_region, TRUE, TRUE);
+ assert(in_jnl_file_autoswitch);
REVERT;
in_jnl_file_autoswitch = FALSE;
jgbl.dont_reset_gbl_jrec_time = jgbl.save_dont_reset_gbl_jrec_time;
DEBUG_ONLY(jgbl.save_dont_reset_gbl_jrec_time = FALSE);
- assert((dba_mm == cs_data->acc_meth) || (csd == cs_data));
- csd = cs_data; /* In MM, wcs_flu() can remap an extended DB, so reset csd to be sure */
} else
- {
- if (SS_NORMAL != jpc->status)
- rts_error_csa(CSA_ARG(csa) VARLSTCNT(7) jnl_status, 4, JNL_LEN_STR(csd),
- DB_LEN_STR(gv_cur_region), jpc->status);
- else
- rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(csd),
- DB_LEN_STR(gv_cur_region));
- }
+ jnl_file_close(gv_cur_region, TRUE, TRUE); /* for jb->last_eof_written, just close */
+ assert((dba_mm == cs_data->acc_meth) || (csd == cs_data));
+ csd = cs_data; /* In MM, wcs_flu() can remap an extended DB, so reset csd to be sure */
assert(!jgbl.forw_phase_recovery || (NULL != jgbl.mur_pini_addr_reset_fnptr));
assert(jgbl.forw_phase_recovery || (NULL == jgbl.mur_pini_addr_reset_fnptr));
if (NULL != jgbl.mur_pini_addr_reset_fnptr)
(*jgbl.mur_pini_addr_reset_fnptr)(csa);
assert(!jnl_info.no_rename);
assert(!jnl_info.no_prev_link);
+ assert(!in_jnl_file_autoswitch);
if (EXIT_NRM == cre_jnl_file(&jnl_info))
{
assert(0 == memcmp(csd->jnl_file_name, jnl_info.jnl, jnl_info.jnl_len));
@@ -245,6 +250,7 @@ uint4 jnl_file_extend(jnl_private_control *jpc, uint4 total_jnl_rec_size)
DB_LEN_STR(gv_cur_region));
}
assert(jb->filesize == csd->jnl_alq);
+ assert(!jb->last_eof_written);
if (csd->jnl_alq + csd->jnl_deq <= csd->autoswitchlimit)
{
aligned_tot_jrec_size = ALIGNED_ROUND_UP(MAX_REQD_JNL_FILE_SIZE(total_jnl_rec_size),
@@ -280,7 +286,6 @@ uint4 jnl_file_extend(jnl_private_control *jpc, uint4 total_jnl_rec_size)
rts_error_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_JNLRDERR, 2, JNL_LEN_STR(csd), jpc->status);
}
assert((header->virtual_size + new_blocks) == new_alq);
- jb->filesize = new_alq; /* Actually this is virtual file size blocks */
header->virtual_size = new_alq;
JNL_DO_FILE_WRITE(csa, csd->jnl_file_name, jpc->channel, 0,
header, read_write_size, jpc->status, jpc->status2);
@@ -289,6 +294,7 @@ uint4 jnl_file_extend(jnl_private_control *jpc, uint4 total_jnl_rec_size)
assert(WBTEST_RECOVER_ENOSPC == gtm_white_box_test_case_number);
rts_error_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_JNLWRERR, 2, JNL_LEN_STR(csd), jpc->status);
}
+ jb->filesize = new_alq; /* Actually this is virtual file size blocks */
}
if (0 >= new_blocks)
break;
@@ -298,7 +304,8 @@ uint4 jnl_file_extend(jnl_private_control *jpc, uint4 total_jnl_rec_size)
INCR_GVSTATS_COUNTER(csa, csa->nl, n_jnl_extends, 1);
return EXIT_NRM;
}
- jpc->status = ERR_JNLREADEOF;
+ if (SS_NORMAL == jpc->status)
+ jpc->status = ERR_JNLREADEOF;
jnl_file_lost(jpc, ERR_JNLEXTEND);
return EXIT_ERR;
}
diff --git a/sr_unix/jnl_file_open.c b/sr_unix/jnl_file_open.c
index 86640bd..b2eca59 100644
--- a/sr_unix/jnl_file_open.c
+++ b/sr_unix/jnl_file_open.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -81,7 +81,7 @@ uint4 jnl_file_open(gd_region *reg, bool init, void *dummy) /* third argument fo
{
assert(csd->jnl_file_len < JNL_NAME_SIZE);
nameptr[csd->jnl_file_len] = 0;
- cre_jnl_file_intrpt_rename(((int)csd->jnl_file_len), csd->jnl_file_name);
+ cre_jnl_file_intrpt_rename(csa);
/* although jnl_file_close() would have reset jnl_file.u.inode and device to 0 and incremented cycle, it
* might have got shot in the middle of executing those instructions. we redo it here just to be safe.
*/
@@ -193,10 +193,8 @@ uint4 jnl_file_open(gd_region *reg, bool init, void *dummy) /* third argument fo
jpc->cycle = jb->cycle; /* make private cycle and shared cycle in sync */
GTM_FD_TRACE_ONLY(
gtm_dbjnl_dupfd_check(); /* Check if db or jnl fds collide (D9I11-002714) */
- if (NOJNL == jpc->channel)
- { /* The dupfd check above has reset our channel. No idea why. */
- GTMASSERT;
- }
+ /* The dupfd check above should not reset our channel. */
+ assertpro(NOJNL != jpc->channel);
)
} /* if jnl_state */
} else
@@ -204,7 +202,8 @@ uint4 jnl_file_open(gd_region *reg, bool init, void *dummy) /* third argument fo
jpc->status = ERR_JNLMOVED;
sts = ERR_JNLOPNERR;
assert(gtm_white_box_test_case_enabled
- && (WBTEST_JNLOPNERR_EXPECTED == gtm_white_box_test_case_number));
+ && ((WBTEST_JNLOPNERR_EXPECTED == gtm_white_box_test_case_number)
+ || (WBTEST_JNL_CREATE_FAIL == gtm_white_box_test_case_number)));
}
} else
{ /* stat failed */
diff --git a/sr_unix/jnlext_write.c b/sr_unix/jnlext_write.c
index caacb9f..7740856 100644
--- a/sr_unix/jnlext_write.c
+++ b/sr_unix/jnlext_write.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,6 +33,7 @@ GBLREF mstr sys_output;
static readonly unsigned char open_params_list[] =
{
+ (unsigned char)iop_stream,
(unsigned char)iop_nowrap,
(unsigned char)iop_eol
};
diff --git a/sr_unix/jnlpool_init.c b/sr_unix/jnlpool_init.c
index 7eb2d55..2acb5ae 100644
--- a/sr_unix/jnlpool_init.c
+++ b/sr_unix/jnlpool_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -64,6 +64,7 @@ GBLREF uint4 process_id;
GBLREF gd_region *gv_cur_region;
GBLREF jnlpool_ctl_ptr_t temp_jnlpool_ctl;
GBLREF gtmsource_options_t gtmsource_options;
+GBLREF gtmrecv_options_t gtmrecv_options;
GBLREF boolean_t pool_init;
GBLREF seq_num seq_num_zero;
GBLREF enum gtmImageTypes image_type;
@@ -114,24 +115,34 @@ error_def(ERR_TEXT);
} \
}
+#define DETACH_FROM_JNLPOOL_IF_NEEDED(RTS_ERROR_OR_GTM_PUTMSG) \
+{ \
+ int status, save_errno; \
+ \
+ if (NULL != jnlpool.jnlpool_ctl) \
+ { \
+ JNLPOOL_SHMDT(status, save_errno); \
+ if (0 > status) \
+ RTS_ERROR_OR_GTM_PUTMSG(CSA_ARG(NULL) VARLSTCNT(5) ERR_REPLWARN, 2, \
+ RTS_ERROR_LITERAL("Could not detach from journal pool"), save_errno); \
+ jnlpool_ctl = NULL; \
+ jnlpool.jnlpool_ctl = NULL; \
+ jnlpool.repl_inst_filehdr = NULL; \
+ jnlpool.gtmsrc_lcl_array = NULL; \
+ jnlpool.gtmsource_local_array = NULL; \
+ jnlpool.jnldata_base = NULL; \
+ jnlpool.jnlpool_dummy_reg->open = FALSE; \
+ pool_init = FALSE; \
+ } \
+}
+
#define DETACH_AND_REMOVE_SHM_AND_SEM \
{ \
if (new_ipc) \
{ \
assert(!IS_GTM_IMAGE); /* Since "gtm_putmsg" is done below ensure it is never GT.M */ \
- if (NULL != jnlpool.jnlpool_ctl) \
- { \
- if (-1 == shmdt((caddr_t)jnlpool.jnlpool_ctl)) \
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_REPLWARN, 2, \
- RTS_ERROR_LITERAL("Could not detach from journal pool"), errno); \
- jnlpool_ctl = NULL; \
- jnlpool.jnlpool_ctl = NULL; \
- jnlpool.repl_inst_filehdr = NULL; \
- jnlpool.gtmsrc_lcl_array = NULL; \
- jnlpool.gtmsource_local_array = NULL; \
- jnlpool.jnldata_base = NULL; \
- pool_init = FALSE; \
- } \
+ assert(NULL != jnlpool.jnlpool_ctl); \
+ DETACH_FROM_JNLPOOL_IF_NEEDED(gtm_putmsg_csa); \
assert(INVALID_SHMID != udi->shmid); \
if (0 != shm_rmid(udi->shmid)) \
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_JNLPOOLSETUP, 0, ERR_TEXT, 2, \
@@ -154,7 +165,7 @@ error_def(ERR_TEXT);
void jnlpool_init(jnlpool_user pool_user, boolean_t gtmsource_startup, boolean_t *jnlpool_creator)
{
boolean_t new_ipc, is_src_srvr, slot_needs_init, reset_gtmsrclcl_info, hold_onto_ftok_sem, srv_alive;
- boolean_t skip_locks;
+ boolean_t cannot_activate, skip_locks;
char machine_name[MAX_MCNAMELEN], instfilename[MAX_FN_LEN + 1], scndry_msg[OUT_BUFF_SIZE];
gd_region *r_save, *reg;
int status, save_errno;
@@ -479,7 +490,7 @@ void jnlpool_init(jnlpool_user pool_user, boolean_t gtmsource_startup, boolean_t
if (new_ipc)
{
jnlpool_ctl->instfreeze_environ_inited = FALSE;
- if (ANTICIPATORY_FREEZE_AVAILABLE && !init_anticipatory_freeze_errors())
+ if (CUSTOM_ERRORS_AVAILABLE && !init_anticipatory_freeze_errors())
{
DETACH_AND_REMOVE_SHM_AND_SEM; /* remove any sem/shm we had created */
udi->grabbed_access_sem = FALSE;
@@ -775,15 +786,32 @@ void jnlpool_init(jnlpool_user pool_user, boolean_t gtmsource_startup, boolean_t
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PRIMARYNOTROOT, 2,
LEN_AND_STR((char *)repl_instance.inst_info.this_instname));
} else
- { /* ACTIVATE was specified. Check if there is only one process attached to the journal
- * pool. If yes, we are guaranteed that it is indeed the passive source server process
- * that we are trying to activate (we can assert this because we know for sure the source
- * server corresponding to this slot "gtmsourcelocal_ptr" is alive and running or else we
- * would have issued a SRCSRVNOTEXIST error earlier). and that this is a case of a
- * transition from propagating primary to root primary. If not, issue ACTIVATEFAIL error.
+ { /* ACTIVATE was specified. Check if there is a receiver server OR update process
+ * attached to the journal pool. If so we cannot allow the ACTIVATE (issue ACTIVATEFAIL
+ * error). Those have to be shut down before the instance can be activated. In addition,
+ * disallow an in-progress receiver server startup command. This is because we dont want
+ * the activate to sneak in between the jnlpool_init and recvpool_init calls done by the
+ * receiver server startup command creating a confusing situation (because the receiver
+ * will be ready to play updates as if this is a secondary but an active source server
+ * will be ready to transmit updates as if this is a primary at the same time).
*/
- assert(NULL != gtmsourcelocal_ptr);
- if (1 != shmstat.shm_nattch)
+ cannot_activate = FALSE;
+ if (INVALID_SEMID != repl_instance.recvpool_semid)
+ { /* Receive pool semaphore is available from instance file header. Use it
+ * to check whether receiver server and/or update process are alive. The easiest
+ * way is to check if the counter semaphore is non-zero.
+ */
+ if (semctl(repl_instance.recvpool_semid, RECV_SERV_COUNT_SEM, GETVAL)
+ || semctl(repl_instance.recvpool_semid, UPD_PROC_COUNT_SEM, GETVAL))
+ cannot_activate = TRUE;
+ } else
+ { /* No receiver server or update process running. But check if a receiver server
+ * startup command is in progress and has already done a jnlpool_init.
+ */
+ if (semctl(repl_instance.jnlpool_semid, RECV_SERV_STARTUP_SEM, GETVAL))
+ cannot_activate = TRUE;
+ }
+ if (cannot_activate)
{
rel_sem_immediate(SOURCE, JNL_POOL_ACCESS_SEM);
udi->grabbed_access_sem = FALSE;
@@ -795,6 +823,23 @@ void jnlpool_init(jnlpool_user pool_user, boolean_t gtmsource_startup, boolean_t
hold_onto_ftok_sem = TRUE;
}
}
+ } else if ((GTMRECEIVE == pool_user) && gtmrecv_options.start)
+ { /* This is a receiver server startup command. Increment RECV_SERV_STARTUP_SEM semaphore for
+ * a later source server activate command to know this command is in progress. We dont do
+ * a corresponding decr_sem later but rely on the OS doing it when the receiver startup command
+ * exits (due to the SEM_UNDO done inside incr_sem).
+ */
+ status = incr_sem(SOURCE, RECV_SERV_STARTUP_SEM);
+ if (0 != status)
+ {
+ save_errno = errno;
+ rel_sem_immediate(SOURCE, JNL_POOL_ACCESS_SEM);
+ udi->grabbed_access_sem = FALSE;
+ udi->counter_acc_incremented = FALSE;
+ ftok_sem_release(jnlpool.jnlpool_dummy_reg, TRUE, TRUE);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_JNLPOOLSETUP, 0, ERR_TEXT, 2,
+ RTS_ERROR_LITERAL("Receiver startup counter semaphore increment failure"), save_errno);
+ }
}
}
if (!csa->nl->glob_sec_init)
@@ -1004,30 +1049,25 @@ void jnlpool_init(jnlpool_user pool_user, boolean_t gtmsource_startup, boolean_t
}
if (!hold_onto_ftok_sem && !ftok_sem_release(jnlpool.jnlpool_dummy_reg, FALSE, FALSE))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_JNLPOOLSETUP);
- pool_init = TRUE;
- ENABLE_FREEZE_ON_ERROR;
+ /* Set up pool_init if jnlpool is still attached (e.g. we could have detached if GTMRELAXED and upd_disabled) */
+ if (NULL != jnlpool.jnlpool_ctl)
+ {
+ pool_init = TRUE;
+ ENABLE_FREEZE_ON_ERROR;
+ }
return;
}
void jnlpool_detach(void)
{
- int status, save_errno;
-
if (TRUE == pool_init)
{
rel_lock(jnlpool.jnlpool_dummy_reg);
mutex_cleanup(jnlpool.jnlpool_dummy_reg);
if (jnlpool.gtmsource_local && (process_id == jnlpool.gtmsource_local->gtmsource_srv_latch.u.parts.latch_pid))
rel_gtmsource_srv_latch(&jnlpool.gtmsource_local->gtmsource_srv_latch);
- JNLPOOL_SHMDT(status, save_errno);
- if (0 > status)
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_REPLWARN, 2,
- RTS_ERROR_LITERAL("Could not detach from journal pool"), save_errno);
- jnlpool.repl_inst_filehdr = NULL;
- jnlpool.gtmsrc_lcl_array = NULL;
- jnlpool.gtmsource_local_array = NULL;
- jnlpool.jnldata_base = NULL;
- pool_init = FALSE;
+ DETACH_FROM_JNLPOOL_IF_NEEDED(rts_error_csa);
+ assert(!pool_init); /* would have been reset by the above macro invocation */
}
}
diff --git a/sr_unix/kitstart.csh b/sr_unix/kitstart.csh
index 65fd13e..cb63b62 100644
--- a/sr_unix/kitstart.csh
+++ b/sr_unix/kitstart.csh
@@ -1,7 +1,7 @@
#!/usr/local/bin/tcsh
#################################################################
# #
-# Copyright 2011, 2013 Fidelity Information Services, Inc #
+# Copyright 2011, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -231,13 +231,10 @@ foreach image ($imagetype)
cd ${tmp_dist}/${image} || exit 7
echo ""
echo "Copying files from ${gtm_ver}/${image}"
- if ("aix" == $osname) then
- /bin/cp -rh ${gtm_ver}/${image}/* . || exit 8
- else if ("solaris" == $osname) then
- /usr/local/bin/cp -r ${gtm_ver}/${image}/* . || exit 8
- else
- /bin/cp -r ${gtm_ver}/${image}/* . || exit 8
- endif
+ set cpflags="-r"
+ if ("aix" == $osname) set cpflags="-rh"
+ if ("solaris" == $osname) set cpflags="-rH"
+ cp ${cpflags} ${gtm_ver}/${image}/* . || exit 8
echo ""
echo "Removing files that are not distributed (${notdistributed})"
/bin/rm -rf ${notdistributed} || exit 9
diff --git a/sr_unix/libdse.list b/sr_unix/libdse.list
index 3d7da99..1a48d1b 100644
--- a/sr_unix/libdse.list
+++ b/sr_unix/libdse.list
@@ -23,6 +23,7 @@ dse_fdmp
dse_find_gvt
dse_find_roots
dse_flush
+dse_getblk
dse_getki
dse_help
dse_integ
diff --git a/sr_unix/libmupip.list b/sr_unix/libmupip.list
index b78fd63..1b5b823 100644
--- a/sr_unix/libmupip.list
+++ b/sr_unix/libmupip.list
@@ -78,6 +78,7 @@ mu_int_read
mu_int_reg
mu_int_reg_ch
mu_int_write
+mu_interactive
mu_op_open
mu_outofband_setup
mu_put_gvdata
@@ -105,7 +106,6 @@ mu_upgrd_header
mubclnup
mubexpfilnam
mubfilcpy
-mubfndreg
mubgetfil
mubinccpy
mucblkini
@@ -164,7 +164,6 @@ mur_get_options
mur_get_pini
mur_init
mur_insert_prev
-mur_interactive
mur_jctl_from_next_gen
mur_jnl_ext
mur_multi_rehash
diff --git a/sr_unix/lintgtm.csh b/sr_unix/lintgtm.csh
index 5bcf7f4..a786b13 100644
--- a/sr_unix/lintgtm.csh
+++ b/sr_unix/lintgtm.csh
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2001, 2010 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -125,12 +125,6 @@ endsw
-if ( $gt_ar_gtmrpc_name == "" ) then
- set gt_lint_gtmrpc_library_option = ""
-else
- set gt_lint_gtmrpc_library_option = "llib-l$gt_ar_gtmrpc_name.ln"
-endif
-
cd $gtm_exe
@@ -154,7 +148,7 @@ chmod +w *.c *.h
set lintgtm_verbose = $?verbose
-set lintgtm_liblist = "dse $gt_ar_gtmrpc_name lke mupip stub mumps"
+set lintgtm_liblist = "dse lke mupip stub mumps"
foreach i ( $lintgtm_liblist )
@@ -164,7 +158,6 @@ foreach i ( $lintgtm_liblist )
switch ( $i )
case "dse":
- case "gtmrpc": # couldn't use "$gt_ar_gtmrpc_name", so had to hard-code "gtmrpc"
case "lke":
case "mupip":
case "stub":
@@ -182,7 +175,7 @@ foreach i ( $lintgtm_liblist )
# Exclude files that define the same externals (e.g., "main" and the VMS CLI [command line interpreter]
# emulator arrays):
pwd
- rm -f gtm.c gtm_svc.c \
+ rm -f gtm.c \
lke.c lke_cmd.c \
dse.c dse_cmd.c \
mupip.c mupip_cmd.c \
@@ -201,15 +194,9 @@ end
# $shell $gtm_tools/lintshr.csh $p1 # for true parallelism, the following commands would be in lintshr.csh
cp $gtm_src/{gtm.c .
-gt_lint $gt_lint_options gtm.c llib-l{mumps,stub}.ln $gt_lint_gtmrpc_library_option $gt_lint_syslibs \
+gt_lint $gt_lint_options gtm.c llib-l{mumps,stub}.ln $gt_lint_syslibs \
>& lint.mumps.log
-if ( $gt_ar_gtmrpc_name != "" ) then
- cp $gtm_src/gtm_svc.c .
- gt_lint $gt_lint_options gtm_svc.c \
- llib-l{mumps,stub}.ln $gt_lint_gtmrpc_library_option $gt_lint_syslibs >& lint.gtm_svc.log
-endif
-
# $shell $gtm_tools/lintaux.csh $p1 # for true parallelism, the following commands would be in lingaux.csh
cp $gtm_src/{dse,dse_cmd}.c .
gt_lint $gt_lint_options {dse,dse_cmd}.c llib-l{dse,mumps,stub}.ln $gt_lint_syslibs >& lint.dse.log
diff --git a/sr_unix/lke.c b/sr_unix/lke.c
index cde233b..22c038e 100644
--- a/sr_unix/lke.c
+++ b/sr_unix/lke.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -46,20 +46,17 @@
#include "gt_timer.h"
#include "lke.h"
#include "lke_fileio.h"
-#include "get_page_size.h"
#include "gtm_startup_chk.h"
#include "generic_signal_handler.h"
#include "init_secshr_addrs.h"
#include "cli_parse.h"
#include "getzdir.h"
#include "getjobname.h"
-#include "getjobnum.h"
#include "sig_init.h"
#include "gtmmsg.h"
#include "suspsigs_handler.h"
#include "patcode.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
#include "gtmio.h"
#include "have_crit.h"
@@ -93,10 +90,7 @@ int main (int argc, char *argv[])
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- set_blocksig();
- gtm_imagetype_init(LKE_IMAGE);
- gtm_wcswidth_fnptr = gtm_wcswidth;
- gtm_env_init(); /* read in all environment variables */
+ common_startup_init(LKE_IMAGE);
licensed = TRUE;
err_init(util_base_ch);
UNICODE_ONLY(gtm_strToTitle_ptr = >m_strToTitle);
@@ -104,7 +98,6 @@ int main (int argc, char *argv[])
sig_init(generic_signal_handler, lke_ctrlc_handler, suspsigs_handler, continue_handler);
atexit(util_exit_handler);
SET_LATCH_GLOBAL(&defer_latch, LOCK_AVAILABLE);
- get_page_size();
stp_init(STP_INITSIZE);
rts_stringpool = stringpool;
getjobname();
@@ -116,7 +109,6 @@ int main (int argc, char *argv[])
initialize_pattern_table();
gvinit();
region_init(TRUE);
- getjobnum();
cli_lex_setup(argc, argv);
/* this should be after cli_lex_setup() due to S390 A/E conversion */
@@ -127,6 +119,7 @@ int main (int argc, char *argv[])
break;
}
lke_exit();
+ return 0;
}
static bool lke_process(int argc)
@@ -137,7 +130,7 @@ static bool lke_process(int argc)
ESTABLISH_RET(util_ch, TRUE);
if (util_interrupt)
- rts_error(VARLSTCNT(1) ERR_CTRLC);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
if (SYS_STDERR != save_stderr) /* necesary in case of rts_error */
close_fileio(&save_stderr);
assert(SYS_STDERR == save_stderr);
@@ -150,7 +143,7 @@ static bool lke_process(int argc)
{
if (util_interrupt)
{
- rts_error(VARLSTCNT(1) ERR_CTRLC);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
REVERT;
return TRUE;
}
@@ -164,9 +157,9 @@ static bool lke_process(int argc)
if (1 < argc)
{
REVERT;
- rts_error(VARLSTCNT(4) res, 2, LEN_AND_STR(cli_err_str));
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) res, 2, LEN_AND_STR(cli_err_str));
} else
- gtm_putmsg(VARLSTCNT(4) res, 2, LEN_AND_STR(cli_err_str));
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) res, 2, LEN_AND_STR(cli_err_str));
}
if (func)
{
diff --git a/sr_unix/lke_ctrlc_handler.c b/sr_unix/lke_ctrlc_handler.c
index 5e28ed7..7162f04 100644
--- a/sr_unix/lke_ctrlc_handler.c
+++ b/sr_unix/lke_ctrlc_handler.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -19,21 +19,9 @@
#include "lke.h"
#include "have_crit.h"
-GBLREF VSIG_ATOMIC_T util_interrupt;
-GBLREF volatile int4 fast_lock_count;
+GBLREF VSIG_ATOMIC_T util_interrupt;
-/* Only allow the process to be interrupted if we are not in crit and not in the process
- of obtaining it. Otherwise, we cannot service this interruption at this time and must
- return (but will set the interruption flag. */
-CONDITION_HANDLER(lke_ctrlc_handler)
+void lke_ctrlc_handler(int sig)
{
- int dummy1, dummy2;
-
- START_CH(TRUE); /* Drive top level condition handler if we can */
util_interrupt = 1;
- if (0 == fast_lock_count && 0 == have_crit(CRIT_HAVE_ANY_REG))
- {
- UNWIND(dummy1, dummy2); /* This will do a longjmp and not 'return' here */
- }
- CONTINUE; /* Unconditional return */
}
diff --git a/sr_unix/load.h b/sr_unix/load.h
index f5a69b7..bc34fb7 100644
--- a/sr_unix/load.h
+++ b/sr_unix/load.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2006 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,27 @@
#ifndef LOAD_INCLUDED
#define LOAD_INCLUDED
+#define ONERROR_STOP 0
+#define ONERROR_PROCEED 1
+#define ONERROR_INTERACTIVE 2
+#define ONERROR_PROCESS \
+{ \
+ GBLREF int onerror; \
+ \
+ if (ONERROR_STOP == onerror) \
+ { \
+ break; \
+ } \
+ if (ONERROR_INTERACTIVE == onerror && !mu_interactive("Load terminated by operator\n")) \
+ { \
+ onerror = ONERROR_STOP; \
+ /* User selected Not to proceed */ \
+ break; \
+ } \
+ mupip_error_occurred = FALSE; \
+ continue; /* continue, when (onerror = ONERROR_PROCEED) or when user selects Yes in ONERROR_INTERACTIVE */ \
+}
+
void bin_load(uint4 begin, uint4 end);
void go_load(uint4 begin, uint4 end);
void goq_load(void);
diff --git a/sr_unix/m_zrupdate.c b/sr_unix/m_zrupdate.c
new file mode 100644
index 0000000..d65f7ec
--- /dev/null
+++ b/sr_unix/m_zrupdate.c
@@ -0,0 +1,63 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include "compiler.h"
+#include "mdq.h"
+#include "opcode.h"
+#include "indir_enum.h"
+#include "toktyp.h"
+#include "advancewindow.h"
+#include "cmd.h"
+
+#ifdef USHBIN_SUPPORTED
+/* Routine to compile ZRUPDATE command
+ *
+ * Current syntax:
+ *
+ * ZRUPDATE <object-file-path1>[,<object-file-path2>..
+ *
+ * Where:
+ *
+ * object-file-path - Is the path and filename of an object file that may include wildcards. We allow multiple specifications
+ * separated by commas. We let cmd.c break these into separate commands.
+ *
+ * Parameters: none
+ * Returncode: success (TRUE) and failure (FALSE)
+ *
+ * Future enhancement - Allow paths to be grouped by surrounding with parens. At that point, this becomes a variable length
+ * parameter list but for now tiz simplistic.
+ */
+int m_zrupdate(void)
+{
+ oprtype objfilespec;
+ triple *triptr;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ switch (expr(&objfilespec, MUMPS_STR))
+ {
+ case EXPR_FAIL:
+ return FALSE;
+ case EXPR_GOOD:
+ triptr = newtriple(OC_ZRUPDATE);
+ triptr->operand[0] = put_ilit(1); /* Currently single arg but that will change for phase2 */
+ triptr->operand[1] = objfilespec;
+ return TRUE;
+ case EXPR_INDR:
+ make_commarg(&objfilespec, indir_zrupdate);
+ return TRUE;
+ }
+ assert(FALSE);
+ return FALSE;
+}
+#endif /* USHBIN_SUPPORTED */
diff --git a/sr_unix/memprot.c b/sr_unix/memprot.c
new file mode 100644
index 0000000..e9bc63c
--- /dev/null
+++ b/sr_unix/memprot.c
@@ -0,0 +1,47 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+#include <sys/mman.h>
+#include "mdef.h"
+#include "memprot.h"
+
+OS_PAGE_SIZE_DECLARE
+
+/*
+ * Ensure base address has at least <size> bytes of accessible space, followed by an inaccessible (PROT_NONE) page.
+ */
+void memprot(mstr *base, uint4 size)
+{
+ int status;
+
+ if (base->len < size)
+ {
+ if (NULL != base->addr)
+ munmap(base->addr, base->len + OS_PAGE_SIZE); /* clear previous allocation */
+ base->len = (mstr_len_t)ROUND_UP(size, OS_PAGE_SIZE);
+ base->addr = (char *)mmap(NULL, base->len + OS_PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (MAP_FAILED == base->addr)
+ {
+ base->len = 0;
+ base->addr = NULL;
+ } else
+ {
+ status = mprotect(base->addr + base->len, OS_PAGE_SIZE, PROT_NONE);
+ if (-1 == status)
+ {
+ munmap(base->addr, base->len + OS_PAGE_SIZE);
+ base->len = 0;
+ base->addr = NULL;
+ }
+ }
+ }
+ return;
+}
diff --git a/sr_avms/release_name.h b/sr_unix/memprot.h
similarity index 52%
copy from sr_avms/release_name.h
copy to sr_unix/memprot.h
index 150f221..afe8c1c 100644
--- a/sr_avms/release_name.h
+++ b/sr_unix/memprot.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -8,7 +8,8 @@
* the license, please stop and do not read further. *
* *
****************************************************************/
-
-#define GTM_RELEASE_NAME "GT.M V6.1-000 VMS AXP"
-#define GTM_PRODUCT "GT.M"
-#define GTM_VERSION "V6.1"
+/*
+ * This function creates protected memory. The created protected memory is always multiple of OS_PAGE_SIZE, so it is advisable to
+ * have input 'size' in the multiple of OS_PAGE_SIZE. The return value is the starting address of the protected memory.
+ */
+void memprot(mstr *base, uint4 size);
diff --git a/sr_unix/mu_decrypt.c b/sr_unix/mu_decrypt.c
index 21660aa..18c8355 100644
--- a/sr_unix/mu_decrypt.c
+++ b/sr_unix/mu_decrypt.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2012 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -49,7 +49,7 @@ int mu_decrypt(char *fname, uint4 off, uint4 len)
if (is_encrypted)
{
INIT_PROC_ENCRYPTION(NULL, gtmcrypt_errno);
- GTMCRYPT_GETKEY(NULL, hash, key_handle, gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(NULL, hash, key_handle, gtmcrypt_errno);
if (0 == gtmcrypt_errno)
GTMCRYPT_DECRYPT(NULL, key_handle, buff, len, NULL, gtmcrypt_errno);
if (0 != gtmcrypt_errno)
diff --git a/sr_unix/mu_extract.c b/sr_unix/mu_extract.c
index c946f99..3dfdff5 100644
--- a/sr_unix/mu_extract.c
+++ b/sr_unix/mu_extract.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -49,10 +49,17 @@
#include "mvalconv.h"
#include "gtm_conv.h"
#include "gtm_utf8.h"
-#include "filestruct.h"
+#include "filestruct.h" /* needed for jnl.h */
#include "hashtab_mname.h"
#include "gvcst_protos.h" /* for gvcst_root_search in DO_OP_GVNAME macro */
#include "change_reg.h" /* for change_reg call in DO_OP_GVNAME macro */
+#include "mu_getlst.h"
+#include "gdskill.h" /* needed for tp.h */
+#include "jnl.h" /* needed for tp.h */
+#include "gdscc.h" /* needed for tp.h */
+#include "buddy_list.h" /* needed for tp.h */
+#include "hashtab_int4.h" /* needed for tp.h */
+#include "tp.h"
GBLREF int (*op_open_ptr)(mval *v, mval *p, int t, mval *mspace);
GBLREF bool mu_ctrlc_occurred;
@@ -64,6 +71,7 @@ GBLREF io_desc *active_device;
GBLREF gv_namehead *gv_target;
GBLREF boolean_t jnlpool_init_needed;
GBLREF mstr sys_output;
+GBLREF tp_region *grlist;
error_def(ERR_EXTRACTCTRLY);
error_def(ERR_EXTRACTFILERR);
@@ -74,6 +82,7 @@ error_def(ERR_NOSELECT);
error_def(ERR_NULLCOLLDIFF);
error_def(ERR_RECORDSTAT);
error_def(ERR_EXTRFILEXISTS);
+error_def(ERR_DBNOREGION);
LITDEF mval mu_bin_datefmt = DEFINE_MVAL_LITERAL(MV_STR, 0, 0, SIZEOF(BIN_HEADER_DATEFMT) - 1,
BIN_HEADER_DATEFMT, 0, 0);
@@ -89,18 +98,18 @@ static unsigned short filename_len;
static unsigned char ochset_set = FALSE;
static readonly unsigned char open_params_list[] =
{
- (unsigned char)iop_recordsize, /* 64K -1 - big enough for MAX_BLK_SZ */
-# ifdef BIGENDIAN
- (unsigned char)0, (unsigned char)0, (unsigned char)255, (unsigned char)255,
-# else
- (unsigned char)255, (unsigned char)255, (unsigned char)0, (unsigned char)0,
-# endif
(unsigned char)iop_noreadonly,
(unsigned char)iop_m,
- (unsigned char)iop_nowrap,
(unsigned char)iop_stream,
+ (unsigned char)iop_nowrap,
+ (unsigned char)iop_eol
+};
+static readonly unsigned char use_params[] =
+{
+ (unsigned char)iop_nowrap,
(unsigned char)iop_eol
};
+
static readonly unsigned char no_param = (unsigned char)iop_eol;
#define BINARY_FORMAT_STRING "BINARY"
@@ -168,10 +177,10 @@ void mu_extract(void)
gtm_chset_t saved_out_set;
coll_hdr extr_collhdr;
int bin_header_size;
- int reg_no;
boolean_t is_any_file_encrypted = FALSE;
gvnh_reg_t *gvnh_reg;
gvnh_spanreg_t *gvspan, *last_gvspan;
+ boolean_t region;
# ifdef GTM_CRYPT
unsigned short encrypted_hash_array_len;
unsigned char *curr_hash_ptr, *encrypted_hash_array_ptr;
@@ -208,6 +217,18 @@ void mu_extract(void)
ochset_set = TRUE;
}
}
+ region = FALSE;
+ if (CLI_PRESENT == cli_present("REGION"))
+ {
+ gvinit(); /*side effect: initializes gv_altkey (used by code below) & gv_currkey (not used by below code)*/
+ mu_getlst("REGION", SIZEOF(tp_region));
+ if (!grlist)
+ {
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DBNOREGION);
+ mupip_exit(ERR_MUNOACTION);
+ }
+ region = TRUE;
+ }
logqualifier = (CLI_NEGATED != cli_present("LOG"));
if (CLI_PRESENT == cli_present("FREEZE"))
freeze = TRUE;
@@ -244,12 +265,20 @@ void mu_extract(void)
}
/* gv_select will select globals */
jnlpool_init_needed = TRUE;
- gv_select(cli_buff, n_len, freeze, (char *)select_text, &gl_head, ®_max_rec, ®_max_key, ®_max_blk, FALSE);
+ gv_select(cli_buff, n_len, freeze, (char *)select_text, &gl_head, ®_max_rec, ®_max_key, ®_max_blk, region);
if (!gl_head.next)
{
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSELECT);
mupip_exit(ERR_NOSELECT);
}
+ if (!region)
+ {
+ for (reg = gd_header->regions, region_top = gd_header->regions + gd_header->n_regions; reg < region_top; reg++)
+ {
+ if (reg->open)
+ insert_region(reg, &(grlist), NULL, SIZEOF(tp_region));
+ }
+ }
/* For binary format, check whether all regions have same null collation order */
if (MU_FMT_BINARY == format)
{
@@ -258,10 +287,10 @@ void mu_extract(void)
encrypted_hash_array_ptr = malloc(encrypted_hash_array_len);
memset(encrypted_hash_array_ptr, 0, encrypted_hash_array_len);
# endif
- for (reg = gd_header->regions, region_top = gd_header->regions + gd_header->n_regions,
- reg_std_null_coll = -1, reg_no = 0;
- reg < region_top ; reg++, reg_no++)
+ tp_region *rptr;
+ for (rptr = grlist, reg_std_null_coll = -1; NULL != rptr; rptr = rptr->fPtr)
{
+ reg=rptr->reg;
if (reg->open)
{
if (reg_std_null_coll != reg->std_null_coll)
@@ -279,7 +308,7 @@ void mu_extract(void)
csd = csa->hdr;
if (csd->is_encrypted)
{
- curr_hash_ptr = encrypted_hash_array_ptr + (reg_no * GTMCRYPT_HASH_LEN);
+ curr_hash_ptr = encrypted_hash_array_ptr + (GTMCRYPT_HASH_LEN * find_reg_hash_idx(reg));
memcpy(curr_hash_ptr, csd->encryption_hash, GTMCRYPT_HASH_LEN);
is_any_file_encrypted = TRUE;
}
@@ -318,8 +347,8 @@ void mu_extract(void)
op_val.mvtype = MV_STR;
(*op_open_ptr)(&op_val, &op_pars, 0, 0);
ESTABLISH(mu_extract_handler);
- op_pars.str.len = SIZEOF(no_param);
- op_pars.str.addr = (char *)&no_param;
+ op_pars.str.len = SIZEOF(use_params);
+ op_pars.str.addr = (char *)&use_params;
op_use(&op_val, &op_pars);
if (MU_FMT_BINARY == format)
{ /* binary header label format:
@@ -504,10 +533,10 @@ void mu_extract(void)
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_EXTRACTCTRLY);
mupip_exit(ERR_MUNOFINISH);
}
- if (0 < grand_total.recknt)
+ if (0 != grand_total.recknt)
{
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_RECORDSTAT, 6, LEN_AND_LIT("TOTAL"),
- grand_total.recknt, grand_total.keylen, grand_total.datalen, grand_total.reclen);
+ &grand_total.recknt, grand_total.keylen, grand_total.datalen, grand_total.reclen);
} else
{
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSELECT);
diff --git a/sr_unix/mu_getlst.c b/sr_unix/mu_getlst.c
index 828c58d..dae62aa 100644
--- a/sr_unix/mu_getlst.c
+++ b/sr_unix/mu_getlst.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -32,22 +32,23 @@
#include "mupip_exit.h"
#include "str_match.h"
#include "mu_getlst.h"
+#include "gtmmsg.h"
+GBLDEF boolean_t is_directory;
GBLDEF mstr directory;
-GBLDEF bool is_directory;
+GBLREF backup_reg_list *mu_repl_inst_reg_list;
GBLREF bool error_mupip;
GBLREF bool in_backup;
+GBLREF boolean_t mu_star_specified;
GBLREF gd_addr *gd_header;
GBLREF tp_region *grlist;
-GBLREF boolean_t mu_star_specified;
-GBLREF backup_reg_list *mu_repl_inst_reg_list;
error_def(ERR_MUBCKNODIR);
error_def(ERR_MUNOACTION);
error_def(ERR_MUNODBNAME);
error_def(ERR_MUPCLIERR);
-error_def(ERR_TEXT);
+error_def(ERR_NOREGION);
#define CHECK_IF_NOT_ABSENT(QUALIFIER) \
{ \
@@ -60,11 +61,11 @@ error_def(ERR_TEXT);
void mu_getlst(char *name, int4 size)
{
- char *c1, *c2, *c3, *c4, rbuff[GTM_PATH_MAX], fbuff[GTM_PATH_MAX];
- unsigned short rlen, flen, i;
+ boolean_t matched;
+ char *c1, *c2, *c3, *c4, fbuff[GTM_PATH_MAX], rbuff[GTM_PATH_MAX];
gd_region *reg;
tp_region *list;
- boolean_t matched;
+ unsigned short flen, i, rlen;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -72,12 +73,15 @@ void mu_getlst(char *name, int4 size)
assert(size > 0);
rlen = SIZEOF(rbuff);
flen = SIZEOF(fbuff);
-
is_directory = FALSE;
if (!in_backup)
{
if (!cli_get_str(name, rbuff, &rlen))
mupip_exit(ERR_MUNODBNAME);
+ for (i = 0; i < rlen; i++)
+ rbuff[i] = TOUPPER(rbuff[i]); /* Region names are always upper-case ASCII and thoroughly NUL terminated */
+ for ( ; i < ARRAYSIZE(rbuff); i++)
+ rbuff[i] = 0;
} else
{
if (CLI_PRESENT == cli_present("REPLINSTANCE"))
@@ -119,6 +123,10 @@ void mu_getlst(char *name, int4 size)
}
if (!cli_get_str(name, rbuff, &rlen))
mupip_exit(ERR_MUNODBNAME);
+ for (i = 0; i < rlen; i++)
+ rbuff[i] = TOUPPER(rbuff[i]); /* Region names are always upper-case ASCII and thoroughly NUL terminated */
+ for ( ; i < ARRAYSIZE(rbuff); i++)
+ rbuff[i] = 0;
flen = SIZEOF(fbuff); /* reset max_buflen to original before call to "cli_get_str" */
if ((!cli_get_str("SAVE_DIR", fbuff, &flen)) || (0 == flen))
mupip_exit(ERR_MUBCKNODIR);
@@ -144,7 +152,7 @@ void mu_getlst(char *name, int4 size)
if (NULL == (list = insert_region(reg, &(grlist), NULL, size)))
{
error_mupip = TRUE;
- rts_error(VARLSTCNT(4) ERR_TEXT, 2, RTS_ERROR_STRING("Region not found"));
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOREGION, 2, REG_LEN_STR(reg));
continue;
}
if ((FALSE == in_backup) || (0 != ((backup_reg_list *)list)->backup_file.len))
@@ -166,7 +174,7 @@ void mu_getlst(char *name, int4 size)
}
if (!matched)
{
- util_out_print("REGION !AD not found", TRUE, c2 - c1, c1);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOREGION, 2, c2 - c1, c1);
mupip_exit(ERR_MUNOACTION);
}
}
diff --git a/sr_unix/mu_replpool_grab_sem.c b/sr_unix/mu_replpool_grab_sem.c
index 297e1d7..fa1d5a7 100644
--- a/sr_unix/mu_replpool_grab_sem.c
+++ b/sr_unix/mu_replpool_grab_sem.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -54,38 +54,38 @@
*sem_created_ptr = SEM_CREATED = FALSE; \
}
-#define DO_CLNUP_AND_RETURN(SAVE_ERRNO, SEM_CREATED, POOL_TYPE, INSTFILENAME, INSTFILELEN, SEM_ID, FAILED_OP) \
-{ \
- REMOVE_SEM_SET(SEM_CREATED, REPLPOOL_ID); \
- gtm_putmsg(VARLSTCNT(5) ERR_REPLACCSEM, 3, SEM_ID, INSTFILELEN, INSTFILENAME); \
- gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \
- return -1; \
+#define DO_CLNUP_AND_RETURN(SAVE_ERRNO, SEM_CREATED, POOL_TYPE, INSTFILENAME, INSTFILELEN, SEM_ID, FAILED_OP) \
+{ \
+ REMOVE_SEM_SET(SEM_CREATED, REPLPOOL_ID); \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_REPLACCSEM, 3, SEM_ID, INSTFILELEN, INSTFILENAME); \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \
+ return -1; \
}
-#define RELEASE_ALREADY_HELD_SEMAPHORE(SEM_SET, SEM_NUM) \
-{ \
- int status, lcl_save_errno; \
- \
- assert(holds_sem[SEM_SET][SEM_NUM]); \
- status = rel_sem_immediate(SEM_SET, SEM_NUM); \
- if (-1 == status) \
- { \
- lcl_save_errno = errno; \
- gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("semop()"), CALLFROM, lcl_save_errno); \
- } \
+#define RELEASE_ALREADY_HELD_SEMAPHORE(SEM_SET, SEM_NUM) \
+{ \
+ int status, lcl_save_errno; \
+ \
+ assert(holds_sem[SEM_SET][SEM_NUM]); \
+ status = rel_sem_immediate(SEM_SET, SEM_NUM); \
+ if (-1 == status) \
+ { \
+ lcl_save_errno = errno; \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("semop()"), CALLFROM, lcl_save_errno); \
+ } \
}
-#define DECR_ALREADY_INCREMENTED_SEMAPHORE(SEM_SET, SEM_NUM) \
-{ \
- int status, lcl_save_errno; \
- \
- assert(holds_sem[SEM_SET][SEM_NUM]); \
- status = decr_sem(SEM_SET, SEM_NUM); \
- if (-1 == status) \
- { \
- lcl_save_errno = errno; \
- gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("semop()"), CALLFROM, lcl_save_errno); \
- } \
+#define DECR_ALREADY_INCREMENTED_SEMAPHORE(SEM_SET, SEM_NUM) \
+{ \
+ int status, lcl_save_errno; \
+ \
+ assert(holds_sem[SEM_SET][SEM_NUM]); \
+ status = decr_sem(SEM_SET, SEM_NUM); \
+ if (-1 == status) \
+ { \
+ lcl_save_errno = errno; \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("semop()"), CALLFROM, lcl_save_errno); \
+ } \
}
GBLREF jnlpool_addrs jnlpool;
@@ -125,7 +125,7 @@ int mu_replpool_grab_sem(repl_inst_hdr_ptr_t repl_inst_filehdr, char pool_type,
SETUP_THREADGBL_ACCESS;
*sem_created_ptr = sem_created = FALSE; /* assume semaphore not created by default */
- force_increment = (jgbl.onlnrlbk || (!jgbl.mur_rollback && !argumentless_rundown && ANTICIPATORY_FREEZE_AVAILABLE));
+ force_increment = (jgbl.onlnrlbk || (!jgbl.mur_rollback && !argumentless_rundown && INST_FREEZE_ON_ERROR_POLICY));
/* First ensure that the caller has grabbed the ftok semaphore on the replication instance file */
assert((NULL != jnlpool.jnlpool_dummy_reg) && (jnlpool.jnlpool_dummy_reg == recvpool.recvpool_dummy_reg));
replreg = jnlpool.jnlpool_dummy_reg;
diff --git a/sr_unix/mu_replpool_release_sem.c b/sr_unix/mu_replpool_release_sem.c
index c3e32b7..cee344a 100644
--- a/sr_unix/mu_replpool_release_sem.c
+++ b/sr_unix/mu_replpool_release_sem.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -45,11 +45,11 @@
#include "ftok_sems.h"
#include "anticipatory_freeze.h"
-#define DO_CLNUP_AND_RETURN(SAVE_ERRNO, INSTFILENAME, INSTFILELEN, SEM_ID, FAILED_OP) \
-{ \
- gtm_putmsg(VARLSTCNT(5) ERR_REPLACCSEM, 3, SEM_ID, INSTFILELEN, INSTFILENAME); \
- gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \
- return -1; \
+#define DO_CLNUP_AND_RETURN(SAVE_ERRNO, INSTFILENAME, INSTFILELEN, SEM_ID, FAILED_OP) \
+{ \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_REPLACCSEM, 3, SEM_ID, INSTFILELEN, INSTFILENAME); \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \
+ return -1; \
}
GBLREF jnlpool_addrs jnlpool;
@@ -91,7 +91,7 @@ int mu_replpool_release_sem(repl_inst_hdr_ptr_t repl_inst_filehdr, char pool_typ
* with anticipatory freeze scheme in effect.
*/
assert((1 == semval) || ((1 <= semval)
- && (jgbl.onlnrlbk || (!jgbl.mur_rollback && !argumentless_rundown && ANTICIPATORY_FREEZE_AVAILABLE))));
+ && (jgbl.onlnrlbk || (!jgbl.mur_rollback && !argumentless_rundown && INST_FREEZE_ON_ERROR_POLICY))));
remove_sem &= (1 == semval); /* we can remove the sem if the caller intends to and the counter semaphore is 1 */
if (0 < semval)
{
diff --git a/sr_unix/mu_rndwn_file.c b/sr_unix/mu_rndwn_file.c
index 4a35255..3a225cf 100644
--- a/sr_unix/mu_rndwn_file.c
+++ b/sr_unix/mu_rndwn_file.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -94,6 +94,9 @@ static sgmnt_data_ptr_t temp_cs_data;
static sgmnt_addrs *temp_cs_addrs;
static boolean_t restore_rndwn_gbl;
static boolean_t mu_rndwn_file_standalone;
+static boolean_t sem_created;
+static boolean_t no_shm_exists;
+static boolean_t shm_status_confirmed;
LITREF char gtm_release_name[];
LITREF int4 gtm_release_name_len;
@@ -211,8 +214,8 @@ boolean_t mu_rndwn_file(gd_region *reg, boolean_t standalone)
int status, save_errno, sopcnt, tsd_size, save_udi_semid = INVALID_SEMID, semop_res, stat_res, rc;
int csd_size;
char now_running[MAX_REL_NAME];
- boolean_t rc_cpt_removed = FALSE, sem_created = FALSE, is_gtm_shm;
- boolean_t glob_sec_init, db_shm_in_sync, remove_shmid, no_shm_exists;
+ boolean_t rc_cpt_removed, is_gtm_shm;
+ boolean_t glob_sec_init, db_shm_in_sync, remove_shmid;
sgmnt_data_ptr_t csd, tsd = NULL;
sgmnt_addrs *csa;
jnl_private_control *jpc;
@@ -238,11 +241,15 @@ boolean_t mu_rndwn_file(gd_region *reg, boolean_t standalone)
jnl_file_header header;
int4 status1;
uint4 status2;
+ int secshrstat;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
mu_rndwn_file_standalone = standalone;
+ rc_cpt_removed = FALSE;
restore_rndwn_gbl = FALSE;
+ sem_created = FALSE;
+ shm_status_confirmed = FALSE;
assert(!jgbl.onlnrlbk);
assert(!mupip_jnl_recover || standalone);
temp_region = gv_cur_region; /* save gv_cur_region wherever there is scope for it to be changed */
@@ -377,6 +384,7 @@ boolean_t mu_rndwn_file(gd_region *reg, boolean_t standalone)
no_shm_exists = (INVALID_SHMID == udi->shmid || -1 == shmctl(udi->shmid, IPC_STAT, &shm_buf) ||
tsd->gt_shm_ctime.ctime != shm_buf.shm_ctime);
# endif
+ shm_status_confirmed = TRUE; /* Now we have ascertained the status of shared memory. */
/* Whether we want to wait for the counter semaphore to become zero NOW (or defer it) depends on the following conditions :
* a) MUPIP RUNDOWN : If shared memory exists, then it is possible that the database we are attempting to rundown does not
* match the existing shared memory (DBSHMNAMEDIFF case). If so, we should not wait for the counter semaphore, but proceed
@@ -488,7 +496,9 @@ boolean_t mu_rndwn_file(gd_region *reg, boolean_t standalone)
}
db_ipcs.fn[db_ipcs.fn_len] = 0;
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa);
- if (0 != send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0))
+ secshrstat = send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0);
+ csa->read_only_fs = (EROFS == secshrstat);
+ if ((0 != secshrstat) && !csa->read_only_fs)
{
RNDWN_ERR("!AD -> gtmsecshr was unable to write header to disk.", reg);
CLNUP_AND_RETURN(reg, udi, tsd, sem_created, udi->counter_acc_incremented);
@@ -1070,8 +1080,19 @@ CONDITION_HANDLER(mu_rndwn_file_ch)
csa = &udi->s_addrs;
DEBUG_ONLY(in_mu_rndwn_file = FALSE);
TREF(donot_write_inctn_in_wcs_recover) = FALSE;
+ if (udi->counter_acc_incremented)
+ { /* Decrement the access control semaphore in case we incremented it. */
+ do_semop(udi->semid, DB_CONTROL_SEM, -1, IPC_NOWAIT | SEM_UNDO);
+ udi->counter_acc_incremented = FALSE;
+ }
+ if (sem_created || (shm_status_confirmed && no_shm_exists))
+ { /* Remove the access control semaphore if either we just created it, or we know for a fact that there is
+ * no shared memory */
+ sem_rmid(udi->semid);
+ udi->semid = INVALID_SEMID;
+ }
if (udi->grabbed_ftok_sem)
- ftok_sem_release(rundown_reg, FALSE, TRUE);
+ ftok_sem_release(rundown_reg, !mu_rndwn_file_standalone, !mu_rndwn_file_standalone);
}
if (restore_rndwn_gbl)
{
diff --git a/sr_unix/mu_rndwn_repl_instance.c b/sr_unix/mu_rndwn_repl_instance.c
index 732f0df..8cb7fb2 100644
--- a/sr_unix/mu_rndwn_repl_instance.c
+++ b/sr_unix/mu_rndwn_repl_instance.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -195,7 +195,8 @@ boolean_t mu_rndwn_repl_instance(replpool_identifier *replpool_id, boolean_t imm
remove_sem = sem_created || (SS_NORMAL == jnlpool_stat);
if (!remove_sem)
add_to_semids_list(repl_instance.jnlpool_semid);
- if (SS_NORMAL == mu_replpool_release_sem(&repl_instance, JNLPOOL_SEGMENT, remove_sem))
+ status = mu_replpool_release_sem(&repl_instance, JNLPOOL_SEGMENT, remove_sem);
+ if ((SS_NORMAL == status) && remove_sem)
{ /* Now that semaphores are removed, reset fields in file header */
if (!sem_created)
{ /* If sem_id was created by mu_replpool_grab_sem then do NOT report the
@@ -216,7 +217,7 @@ boolean_t mu_rndwn_repl_instance(replpool_identifier *replpool_id, boolean_t imm
{ /* Anticipatory Freeze scheme is turned ON. So, release just the JNL_POOL_ACCESS_SEM. The
* semaphore will be released/removed in the caller (mupip_rundown)
*/
- assert(ANTICIPATORY_FREEZE_AVAILABLE);
+ assert(INST_FREEZE_ON_ERROR_POLICY);
assertpro(SS_NORMAL == (status = rel_sem(SOURCE, JNL_POOL_ACCESS_SEM)));
assert(!holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]);
/* Since we are not resetting the semaphore IDs in the file header, we need to write out
@@ -280,7 +281,8 @@ boolean_t mu_rndwn_repl_instance(replpool_identifier *replpool_id, boolean_t imm
remove_sem = sem_created || (SS_NORMAL == jnlpool_stat);
if (!remove_sem)
add_to_semids_list(repl_instance.jnlpool_semid);
- if (SS_NORMAL == mu_replpool_release_sem(&repl_instance, RECVPOOL_SEGMENT, remove_sem))
+ status = mu_replpool_release_sem(&repl_instance, RECVPOOL_SEGMENT, remove_sem);
+ if ((SS_NORMAL == status) && remove_sem)
{ /* Now that semaphores are removed, reset fields in file header */
if (!sem_created)
{ /* if sem_id was "created" by mu_replpool_grab_sem then do NOT report the
@@ -328,10 +330,10 @@ boolean_t mu_rndwn_repl_instance(replpool_identifier *replpool_id, boolean_t imm
LEN_AND_STR(instfilename));
}
}
- assert(jgbl.onlnrlbk || ANTICIPATORY_FREEZE_AVAILABLE || (NULL == jnlpool.repl_inst_filehdr));
+ assert(jgbl.onlnrlbk || INST_FREEZE_ON_ERROR_POLICY || (NULL == jnlpool.repl_inst_filehdr));
if (mur_options.rollback && (SS_NORMAL == jnlpool_stat) && (SS_NORMAL == recvpool_stat))
{
- assert(jgbl.onlnrlbk || ANTICIPATORY_FREEZE_AVAILABLE || ((INVALID_SHMID == repl_instance.jnlpool_shmid)
+ assert(jgbl.onlnrlbk || INST_FREEZE_ON_ERROR_POLICY || ((INVALID_SHMID == repl_instance.jnlpool_shmid)
&& (INVALID_SHMID == repl_instance.recvpool_shmid)));
/* Initialize jnlpool.repl_inst_filehdr as it is used later by gtmrecv_fetchresync() */
decr_cnt = FALSE;
diff --git a/sr_unix/mu_rndwn_replpool.c b/sr_unix/mu_rndwn_replpool.c
index 350e614..a2d3e34 100644
--- a/sr_unix/mu_rndwn_replpool.c
+++ b/sr_unix/mu_rndwn_replpool.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -75,60 +75,30 @@ error_def(ERR_REPLPOOLINST);
error_def(ERR_SYSCALL);
error_def(ERR_TEXT);
-#define ISSUE_REPLPOOLINST_AND_RETURN(SAVE_ERRNO, SHM_ID, INSTFILENAME, FAILED_OP) \
-{ \
- ISSUE_REPLPOOLINST(SAVE_ERRNO, SHM_ID, INSTFILENAME, FAILED_OP) \
- return -1; \
+#define DETACH(START_ADDR, SHM_ID, INSTFILENAME) \
+{ \
+ int lcl_save_errno; \
+ \
+ if (-1 == shmdt((void *)START_ADDR)) \
+ { \
+ lcl_save_errno = errno; \
+ ISSUE_REPLPOOLINST(lcl_save_errno, SHM_ID, INSTFILENAME, "shmdt()"); \
+ } \
}
-#define DETACH_AND_RETURN(START_ADDR, SHM_ID, INSTFILENAME) \
-{ \
- int lcl_save_errno; \
- \
- if (-1 == shmdt((void *)START_ADDR)) \
- { \
- lcl_save_errno = errno; \
- ISSUE_REPLPOOLINST_AND_RETURN(lcl_save_errno, SHM_ID, INSTFILENAME, "shmdt()"); \
- } \
- return -1; \
-}
-
-int mu_rndwn_replpool(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t repl_inst_filehdr, int shm_id, boolean_t *ipc_rmvd)
+int mu_rndwn_replpool2(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t repl_inst_filehdr, int shm_id, boolean_t *ipc_rmvd,
+ char *instfilename, sm_uc_ptr_t start_addr, int nattch)
{
- int semval, status, save_errno, nattch;
- char *instfilename, pool_type;
- sm_uc_ptr_t start_addr;
- struct shmid_ds shm_buf;
+ int save_errno;
+ char pool_type;
unix_db_info *udi;
sgmnt_addrs *csa;
- boolean_t anticipatory_freeze_available, force_attach;
+ boolean_t anticipatory_freeze_available, reset_crash;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- assert(INVALID_SHMID != shm_id);
- instfilename = replpool_id->instfilename;
pool_type = replpool_id->pool_type;
- assert((JNLPOOL_SEGMENT == pool_type) || (RECVPOOL_SEGMENT == pool_type));
- anticipatory_freeze_available = ANTICIPATORY_FREEZE_AVAILABLE;
- force_attach = (jgbl.onlnrlbk || (!jgbl.mur_rollback && !argumentless_rundown && anticipatory_freeze_available));
- if (-1 == shmctl(shm_id, IPC_STAT, &shm_buf))
- {
- save_errno = errno;
- ISSUE_REPLPOOLINST_AND_RETURN(save_errno, shm_id, instfilename, "shmctl()");
- }
- nattch = shm_buf.shm_nattch;
- if ((0 != nattch) && !force_attach)
- {
- util_out_print("Replpool segment (id = !UL) for replication instance !AD is in use by another process.",
- TRUE, shm_id, LEN_AND_STR(instfilename));
- return -1;
- }
- if (-1 == (sm_long_t)(start_addr = (sm_uc_ptr_t) do_shmat(shm_id, 0, 0)))
- {
- save_errno = errno;
- ISSUE_REPLPOOLINST_AND_RETURN(save_errno, shm_id, instfilename, "shmat()");
- }
- ESTABLISH_RET(mu_rndwn_replpool_ch, -1);
+ anticipatory_freeze_available = INST_FREEZE_ON_ERROR_POLICY;
/* assert that the identifiers are at the top of replpool control structure */
assert(0 == offsetof(jnlpool_ctl_struct, jnlpool_id));
assert(0 == offsetof(recvpool_ctl_struct, recvpool_id));
@@ -142,15 +112,18 @@ int mu_rndwn_replpool(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t rep
else
util_out_print("Incorrect replpool format for the segment (id = !UL) belonging to replication instance !AD",
TRUE, shm_id, LEN_AND_STR(instfilename));
- DETACH_AND_RETURN(start_addr, shm_id, instfilename);
+ DETACH(start_addr, shm_id, instfilename);
+ return -1;
}
if (memcmp(replpool_id->now_running, gtm_release_name, gtm_release_name_len + 1))
{
util_out_print("Attempt to access with version !AD, while already using !AD for replpool segment (id = !UL)"
" belonging to replication instance !AD.", TRUE, gtm_release_name_len, gtm_release_name,
LEN_AND_STR(replpool_id->now_running), shm_id, LEN_AND_STR(instfilename));
- DETACH_AND_RETURN(start_addr, shm_id, instfilename);
+ DETACH(start_addr, shm_id, instfilename);
+ return -1;
}
+ reset_crash = (!anticipatory_freeze_available || argumentless_rundown);
/* Assert that if we haven't yet attached to the journal pool yet, jnlpool_ctl better be NULL */
assert((JNLPOOL_SEGMENT != pool_type) || (NULL == jnlpool.jnlpool_ctl));
if (JNLPOOL_SEGMENT == pool_type)
@@ -187,11 +160,11 @@ int mu_rndwn_replpool(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t rep
&& (0 != repl_inst_filehdr->jnlpool_semid_ctime));
jnlpool.repl_inst_filehdr->jnlpool_semid = repl_inst_filehdr->jnlpool_semid;
jnlpool.repl_inst_filehdr->jnlpool_semid_ctime = repl_inst_filehdr->jnlpool_semid_ctime;
- repl_inst_flush_jnlpool(FALSE, !anticipatory_freeze_available);
- assert(!jnlpool.repl_inst_filehdr->crash || anticipatory_freeze_available);
+ repl_inst_flush_jnlpool(FALSE, reset_crash);
+ assert(!jnlpool.repl_inst_filehdr->crash || !reset_crash);
/* Refresh local copy (repl_inst_filehdr) with the copy that was just flushed (jnlpool.repl_inst_filehdr) */
memcpy(repl_inst_filehdr, jnlpool.repl_inst_filehdr, SIZEOF(repl_inst_hdr));
- if (!anticipatory_freeze_available || argumentless_rundown)
+ if (reset_crash)
{ /* Now that jnlpool has been flushed and there is going to be no journal pool, reset
* "jnlpool.repl_inst_filehdr" as otherwise other routines (e.g. "repl_inst_recvpool_reset") are
* affected by whether this is NULL or not.
@@ -205,17 +178,19 @@ int mu_rndwn_replpool(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t rep
}
} /* else we are ONLINE ROLLBACK. repl_inst_flush_jnlpool will be done later after gvcst_init in mur_open_files */
}
- if ((0 == nattch) && (!anticipatory_freeze_available || argumentless_rundown || (RECVPOOL_SEGMENT == pool_type)))
+ if ((0 == nattch) && (reset_crash || (RECVPOOL_SEGMENT == pool_type)))
{
if (-1 == shmdt((caddr_t)start_addr))
{
save_errno = errno;
- ISSUE_REPLPOOLINST_AND_RETURN(save_errno, shm_id, instfilename, "shmdt()");
+ ISSUE_REPLPOOLINST(save_errno, shm_id, instfilename, "shmdt()");
+ return -1;
}
if (0 != shm_rmid(shm_id))
{
save_errno = errno;
- ISSUE_REPLPOOLINST_AND_RETURN(save_errno, shm_id, instfilename, "shm_rmid()");
+ ISSUE_REPLPOOLINST(save_errno, shm_id, instfilename, "shm_rmid()");
+ return -1;
}
if (JNLPOOL_SEGMENT == pool_type)
{
@@ -244,10 +219,49 @@ int mu_rndwn_replpool(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t rep
if (RECVPOOL_SEGMENT == pool_type)
*ipc_rmvd = FALSE;
}
- REVERT;
return 0;
}
+int mu_rndwn_replpool(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t repl_inst_filehdr, int shm_id, boolean_t *ipc_rmvd)
+{
+ int status, save_errno, nattch;
+ char *instfilename;
+ sm_uc_ptr_t start_addr;
+ struct shmid_ds shm_buf;
+ boolean_t force_attach;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+
+ assert(INVALID_SHMID != shm_id);
+ instfilename = replpool_id->instfilename;
+ assert((JNLPOOL_SEGMENT == replpool_id->pool_type) || (RECVPOOL_SEGMENT == replpool_id->pool_type));
+ force_attach = (jgbl.onlnrlbk || (!jgbl.mur_rollback && !argumentless_rundown && INST_FREEZE_ON_ERROR_POLICY));
+ if (-1 == shmctl(shm_id, IPC_STAT, &shm_buf))
+ {
+ save_errno = errno;
+ ISSUE_REPLPOOLINST(save_errno, shm_id, instfilename, "shmctl()");
+ return -1;
+ }
+ nattch = shm_buf.shm_nattch;
+ if ((0 != nattch) && !force_attach)
+ {
+ util_out_print("Replpool segment (id = !UL) for replication instance !AD is in use by another process.",
+ TRUE, shm_id, LEN_AND_STR(instfilename));
+ return -1;
+ }
+ if (-1 == (sm_long_t)(start_addr = (sm_uc_ptr_t) do_shmat(shm_id, 0, 0)))
+ {
+ save_errno = errno;
+ ISSUE_REPLPOOLINST(save_errno, shm_id, instfilename, "shmat()");
+ return -1;
+ }
+ ESTABLISH_RET(mu_rndwn_replpool_ch, -1);
+ status = mu_rndwn_replpool2(replpool_id, repl_inst_filehdr, shm_id, ipc_rmvd, instfilename, start_addr, nattch);
+ REVERT;
+ return status;
+}
+
CONDITION_HANDLER(mu_rndwn_replpool_ch)
{
unix_db_info *udi;
diff --git a/sr_unix/mu_rndwn_replpool.h b/sr_unix/mu_rndwn_replpool.h
index dbda8a6..e084483 100644
--- a/sr_unix/mu_rndwn_replpool.h
+++ b/sr_unix/mu_rndwn_replpool.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,15 +13,17 @@
#define MU_RNDWN_REPLPOOL_INCLUDED
int mu_rndwn_replpool(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t repl_inst_filehdr, int shmid, boolean_t *ipc_rmvd);
+int mu_rndwn_replpool2(replpool_identifier *replpool_id, repl_inst_hdr_ptr_t repl_inst_filehdr, int shm_id, boolean_t *ipc_rmvd,
+ char *instfilename, sm_uc_ptr_t start_addr, int nattch);
int mu_replpool_grab_sem(repl_inst_hdr_ptr_t repl_inst_filehdr, char pool_type, boolean_t *sem_created, boolean_t immediate);
int mu_replpool_release_sem(repl_inst_hdr_ptr_t repl_inst_filehdr, char pool_type, boolean_t remove_sem);
#define MAX_IPCS_ID_BUF 64 /* Shared memory or semaphore ID is an int and so won't be more than 12 digits long */
-#define ISSUE_REPLPOOLINST(SAVE_ERRNO, SHM_ID, INSTFILENAME, FAILED_OP) \
-{ \
- gtm_putmsg(VARLSTCNT(5) ERR_REPLPOOLINST, 3, SHM_ID, LEN_AND_STR(INSTFILENAME)); \
- gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \
+#define ISSUE_REPLPOOLINST(SAVE_ERRNO, SHM_ID, INSTFILENAME, FAILED_OP) \
+{ \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_REPLPOOLINST, 3, SHM_ID, LEN_AND_STR(INSTFILENAME)); \
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \
}
#endif /* MU_RNDWN_REPLPOOL_INCLUDED */
diff --git a/sr_unix/mu_size_arsample.c b/sr_unix/mu_size_arsample.c
index 79b9c7a..2a00629 100644
--- a/sr_unix/mu_size_arsample.c
+++ b/sr_unix/mu_size_arsample.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012, 2013 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,15 +21,12 @@
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
-#include "jnl.h"
#include "gdsblkops.h"
#include "gdskill.h"
#include "gdscc.h"
-#include "copy.h"
#include "interlock.h"
#include "muextr.h"
#include "mu_reorg.h"
-
/* Include prototypes */
#include "t_end.h"
#include "t_retry.h"
@@ -47,11 +44,9 @@
#include "wcs_sleep.h"
#include "memcoherency.h"
#include "change_reg.h"
-
#include "gtm_time.h"
#include "mvalconv.h"
-#include "t_qread.h"
-#include "longset.h" /* needed for cws_insert.h */
+#include "longset.h" /* needed for cws_insert.h */
#include "hashtab_int4.h"
#include "cws_insert.h"
#include "min_max.h"
@@ -62,24 +57,25 @@ error_def(ERR_MUSIZEFAIL);
GBLREF bool mu_ctrlc_occurred;
GBLREF bool mu_ctrly_occurred;
+GBLREF gv_namehead *gv_target;
+GBLREF inctn_opcode_t inctn_opcode;
+GBLREF int muint_adj;
+GBLREF int4 mu_int_adj[];
+GBLREF int4 process_id;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF gv_namehead *gv_target;
GBLREF unsigned int t_tries;
-GBLREF int4 process_id;
-GBLREF inctn_opcode_t inctn_opcode;
-GBLREF unsigned char rdfail_detail;
-#define MAX_RECS_PER_BLK 65535
-#define MAX_RELIABLE 10000 /* Used to tweak the error estimates */
-#define EPS 1e-6
#define APPROX_F_MAX 500 /* Approximate upper bound for the number of records per index block in
- * a realistic database.
+ * a database. The estimated max fanning factor is initially APPROX_F_MAX.
+ * After DYNAMIC_F_MAX samples, we try to get a closer approximation, by
+ * dynamically adjusting the estimated max fanning factor to be EXTRA_F_MAX
+ * more than the maximum fanning observed ("fanning" is number of records in
+ * a block a particular level). We want a closer approximation so that we reject
+ * fewer samples, and therefore get a size estimation more quickly
*/
-#define DYNAMIC_F_MAX 10 /* Choice of these two constants relates to choice of APPROX_F_MAX */
+#define DYNAMIC_F_MAX 10 /* Choice of these two constants relates to choice of APPROX_F_MAX - how? */
#define EXTRA_F_MAX 50
-#define SQR(X) ((double)(X) * (double)(X))
-#define ROUND(X) ((int)((X) + 0.5)) /* c89 does not have round() and some Solaris machines uses that compiler */
typedef struct
{ /* cumulative running stats */
@@ -95,6 +91,7 @@ typedef struct
*/
double f_max[MAX_BT_DEPTH + 1]; /* estimated max fanning factor */
double r_max[MAX_BT_DEPTH + 1]; /* max records found in a block at a given level */
+ double A[MAX_BT_DEPTH + 1]; /* A[j] := mean of a[j] over previous n traversals]; see note on M */
/* Final estimates */
double blktot[MAX_BT_DEPTH + 1]; /* estimated #blocks at each level */
double blkerr[MAX_BT_DEPTH + 1]; /* approximate variance of blktot */
@@ -102,27 +99,19 @@ typedef struct
double B; /* estimated total blocks */
double error; /* approximate error in estimate B */
double R; /* estimated total records */
+ double AT; /* estimated total adjacency */
} stat_t;
-STATICFNDCL void finalize_stats_ar(stat_t *stat, boolean_t ar);
-STATICFNDCL void accum_stats_ar(stat_t *stat, double *r, boolean_t ar);
-
-#define CLEAR_VECTOR(v) \
-{ \
- int j; \
- \
- for (j = 0; j <= MAX_BT_DEPTH; j++) \
- v[j] = 0; \
-}
+/* macro makes it convenient to manange initialization with changes to stat_t */
#define INIT_STATS(stat) \
{ \
- int j; \
+ int J; \
\
stat.n = 0; \
- for (j = 0; j <= MAX_BT_DEPTH; j++) \
+ for (J = 0; MAX_BT_DEPTH >= J; J++) \
{ \
- stat.f_max[j] = APPROX_F_MAX; \
- stat.r_max[j] = 1; \
+ stat.f_max[J] = APPROX_F_MAX; \
+ stat.r_max[J] = 1; \
} \
CLEAR_VECTOR(stat.N); \
CLEAR_VECTOR(stat.M); \
@@ -130,34 +119,36 @@ STATICFNDCL void accum_stats_ar(stat_t *stat, double *r, boolean_t ar);
CLEAR_VECTOR(stat.blktot); \
CLEAR_VECTOR(stat.blkerr); \
CLEAR_VECTOR(stat.rectot); \
+ CLEAR_VECTOR(stat.A); \
}
+STATICFNDCL void accum_stats_ar(stat_t *stat, double *r, double *a);
+STATICFNDCL void finalize_stats_ar(stat_t *stat);
-int4 mu_size_arsample(glist *gl_ptr, uint4 M, boolean_t ar, int seed)
+int4 mu_size_arsample(glist *gl_ptr, uint4 M, int seed)
{
+ boolean_t tn_aborted;
+ double a[MAX_BT_DEPTH + 1]; /* a[j] is # of adjacent block pointers in level j block of cur traversal */
+ double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */
enum cdb_sc status;
- trans_num ret_tn;
int k, h;
- boolean_t verify_reads;
- boolean_t tn_aborted;
+ stat_t rstat;
+ trans_num ret_tn;
unsigned int lcl_t_tries;
- double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */
- stat_t rstat, ustat;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
inctn_opcode = inctn_invalid_op;
+ /* set gv_target/gv_currkey/gv_cur_region/cs_addrs/cs_data to correspond to <globalname,reg> in gl_ptr */
DO_OP_GVNAME(gl_ptr);
- /* sets gv_target/gv_currkey/gv_cur_region/cs_addrs/cs_data to correspond to <globalname,reg> in gl_ptr */
if (0 == gv_target->root)
- { /* Global does not exist (online rollback). Not an error. */
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_GBLNOEXIST, 2, GNAME(gl_ptr).len, GNAME(gl_ptr).addr);
- return EXIT_NRM;
- }
+ { /* Global does not exist (online rollback). Not an error. */
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_GBLNOEXIST, 2, GNAME(gl_ptr).len, GNAME(gl_ptr).addr);
+ return EXIT_NRM;
+ }
if (!seed)
seed = (int4)(time(0) * process_id);
srand48(seed);
-
/* do random traversals until M of them are accepted at level 1 */
INIT_STATS(rstat);
for (k = 1; rstat.N[1] < M; k++)
@@ -168,103 +159,96 @@ int4 mu_size_arsample(glist *gl_ptr, uint4 M, boolean_t ar, int seed)
for (;;)
{
CLEAR_VECTOR(r);
- if (cdb_sc_normal != (status = rand_traverse(r)))
+ CLEAR_VECTOR(a);
+ if (cdb_sc_normal != (status = mu_size_rand_traverse(r, a))) /* WARNING assignment */
{
assert(CDB_STAGNATE > t_tries);
t_retry(status);
continue;
}
gv_target->clue.end = 0;
- gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */
+ gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */
DEBUG_ONLY(lcl_t_tries = t_tries);
- if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED)))
+ if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED))) /* WARNING: assignment */
{
ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted);
if (tn_aborted)
{ /* Global does not exist (online rollback). Not an error. */
- gtm_putmsg_csa(CSA_ARG(NULL)
+ gtm_putmsg_csa(CSA_ARG(NULL)
VARLSTCNT(4) ERR_GBLNOEXIST, 2, GNAME(gl_ptr).len, GNAME(gl_ptr).addr);
return EXIT_NRM;
}
continue;
}
- accum_stats_ar(&rstat, r, ar);
+ accum_stats_ar(&rstat, r, a);
break;
}
}
- finalize_stats_ar(&rstat, ar);
-
- /* display rstat data */
- /* Showing the error as 2 standard deviations which is a 95% confidence interval for the mean number of blocks at
- * each level*/
+ finalize_stats_ar(&rstat);
+ /* display rstat data
+ * Showing error as 2 standard deviations which is a 95% confidence interval for the mean number of blocks at each level
+ */
util_out_print("!/Number of generated samples = !UL", FLUSH, rstat.n);
util_out_print("Number of accepted samples = !UL", FLUSH, rstat.N[1]);
- util_out_print("Level Blocks 2 sigma(+/-) % Accepted", FLUSH);
- for (h = MAX_BT_DEPTH; (h >= 0) && (rstat.blktot[h] < EPS); h--);
+ util_out_print("Level Blocks Adjacent 2 sigma(+/-) % Accepted", FLUSH);
+ for (h = MAX_BT_DEPTH; (0 <= h) && (rstat.blktot[h] < EPS); h--)
+ ;
for ( ; h > 0; h--)
- util_out_print("!5UL !15UL !15UL ~ !3UL% !15UL", FLUSH, h, (int)ROUND(rstat.blktot[h]),
- (int)ROUND(sqrt(rstat.blkerr[h])*2),
- (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100),
- (int)ROUND(100.0*rstat.N[h]/rstat.n)
+ util_out_print("!5UL !15UL !15UL !15UL ~ !3UL% !15UL", FLUSH, h, (int)ROUND(rstat.blktot[h]),
+ (int)ROUND(sqrt(rstat.blkerr[h]) * 2),
+ (int)ROUND(mu_int_adj[h]),
+ (int)ROUND(sqrt(rstat.blkerr[h]) * 2 / rstat.blktot[h] * 100),
+ (int)ROUND(100.0 * rstat.N[h] / rstat.n)
);
- util_out_print("!5UL !15UL !15UL ~ !3UL% N/A", FLUSH, h, (int)ROUND(rstat.blktot[h]),
- (int)ROUND(sqrt(rstat.blkerr[h])*2),
- (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0)
+ util_out_print("!5UL !15UL !15UL !15UL ~ !3UL% N/A", FLUSH, h, (int)ROUND(rstat.blktot[h]),
+ (int)ROUND(mu_int_adj[h]),
+ (int)ROUND(sqrt(rstat.blkerr[h]) * 2),
+ (int)ROUND(sqrt(rstat.blkerr[h]) * 2 / rstat.blktot[h] * 100.0)
);
- util_out_print("Total !15UL !15UL ~ !3UL% N/A", FLUSH, (int)ROUND(rstat.B),
- (int)ROUND(sqrt(rstat.error)*2),
- (int)ROUND(sqrt(rstat.error)*2/rstat.B*100.0)
+ util_out_print("Total !15UL !15UL !15UL ~ !3UL% N/A", FLUSH, (int)ROUND(rstat.B),
+ (int)ROUND(rstat.AT),
+ (int)ROUND(sqrt(rstat.error) * 2),
+ (int)ROUND(sqrt(rstat.error) * 2 / rstat.B * 100.0)
);
-
return EXIT_NRM;
}
-
-void accum_stats_ar(stat_t *stat, double *r, boolean_t ar)
+STATICFNDCL void accum_stats_ar(stat_t *stat, double *r, double *a)
{
+ double random, M0, accept[MAX_BT_DEPTH + 1];
int j, depth, n;
- double random, M0, accept[MAX_BT_DEPTH + 1];
++stat->n;
- for (j = MAX_BT_DEPTH; (j >= 0) && (r[j] < EPS); j--)
+ for (j = MAX_BT_DEPTH; (0 <= j) && (r[j] < EPS); j--)
accept[j] = 0;
depth = j;
- assert(depth >= 0); /* r[0] should remain zero since we don't maintain it */
+ assert(0 <= depth); /* r[0] should remain zero since we don't maintain it */
accept[depth] = 1; /* always accept the root */
- for (j = depth - 1; j >= 1; j--)
- {
- if (!ar)
- accept[j] = 1; /* don't reject anything */
- else if (j == depth - 1)
- accept[j] = accept[j + 1]; /* always accept level beneath root, too */
- else
- accept[j] = accept[j + 1] * (r[j + 1] / stat->f_max[j + 1]);
- }
+ for (; 2 <= j; j--)
+ accept[j - 1] = accept[j] * ((j == depth) ? 1 : (r[j] / stat->f_max[j]));
accept[0] = 0; /* computing #blks (e.g #recs in lvl 1+), not #recs in lvl 0+ */
-
random = drand48();
- for (j = 0; j <= MAX_BT_DEPTH; j++)
+ for (j = 0; MAX_BT_DEPTH >= j; j++)
{
if (random < accept[j])
{
n = ++stat->N[j];
M0 = stat->M[j];
- stat->M[j] += (r[j] - stat->M[j]) / n;
+ stat->M[j] += ((r[j] - M0) / n);
stat->S[j] += (r[j] - stat->M[j]) * (r[j] - M0);
if (n > DYNAMIC_F_MAX)
stat->f_max[j] = stat->r_max[j] + EXTRA_F_MAX;
+ stat->A[j] += ((a[j] - stat->A[j]) / n);
}
stat->r_max[j] = MAX(stat->r_max[j], r[j]);
}
}
-
-void finalize_stats_ar(stat_t *stat, boolean_t ar)
+STATICFNDCL void finalize_stats_ar(stat_t *stat)
{
- int j;
- double factor;
+ int j, k;
- for (j = 0; j <= MAX_BT_DEPTH; j++)
+ for (j = 0; MAX_BT_DEPTH >= j; j++)
/* Variance of the mean (mean referes to avg number of records per block) is Var(R)/N where N is samples size */
if (stat->N[j] > 0)
{
@@ -272,132 +256,28 @@ void finalize_stats_ar(stat_t *stat, boolean_t ar)
stat->S[j] /= stat->N[j];
}
stat->N[0] = stat->n; /* for arithmetic below */
- for (j = MAX_BT_DEPTH; (j >= 0) && (stat->M[j] < EPS); j--);
- assert(j >= 0); /* stat->M[0] should remain zero since we don't maintain it */
- stat->blktot[j] = 1;
- stat->blkerr[j] = 0;
- for (j-- ; j >= 0; j--)
+ for (j = MAX_BT_DEPTH; (0 <= j) && (stat->M[j] < EPS); j--)
+ ;
+ assert(0 <= j); /* stat->M[0] should remain zero since we don't maintain it */
+ mu_int_adj[j] = stat->AT = stat->blkerr[j] = stat->error = 0;
+ stat->B = stat->blktot[j] = 1;
+ for (k = j - 1; j > 0; j--, k--)
{
- if (stat->M[j + 1] == 0)
- stat->M[j + 1] = EPS; /* remove any chance of division by zero */
- stat->blktot[j] = stat->blktot[j + 1] * stat->M[j + 1];
+ if (0 == stat->M[j])
+ stat->M[j] = EPS; /* remove any chance of division by zero */
+ stat->blktot[k] = stat->blktot[j] * stat->M[j];
+ stat->B += stat->blktot[k];
+ mu_int_adj[k] = stat->blktot[j] * stat->A[j];
+ stat->AT += mu_int_adj[k];
/* Var(XY) assuming X and Y are independent = E[X]^2*Var(Y) + E[Y]^2*Var(X) + Var(X)*Var(Y) */
- stat->blkerr[j] = SQR(stat->M[j + 1])*stat->blkerr[j + 1] +
- SQR(stat->blktot[j + 1])*stat->S[j + 1] + stat->blkerr[j + 1]*stat->S[j + 1];
- }
- stat->B = 0;
- stat->error = 0;
- for (j = 0; j <= MAX_BT_DEPTH; j++)
- {
- stat->B += stat->blktot[j];
- stat->error += stat->blkerr[j];
+ stat->blkerr[k] = SQR(stat->M[j]) * stat->blkerr[j]
+ + SQR(stat->blktot[j]) * stat->S[j] + stat->blkerr[j] * stat->S[j];
+ stat->error += stat->blkerr[k];
}
stat->R = 0;
- for (j = 0; j <= MAX_BT_DEPTH; j++)
+ for (j = 0; MAX_BT_DEPTH >= j; j++)
{
stat->rectot[j] = stat->blktot[j] * stat->M[j];
stat->R += stat->rectot[j];
}
}
-
-
-/*
- * Performs a random traversal for the sampling methods
- */
-enum cdb_sc rand_traverse(double *r)
-{
- sm_uc_ptr_t pVal, pTop, pRec, pBlkBase;
- register gv_namehead *pTarg;
- register srch_blk_status *pCurr;
- register srch_hist *pTargHist;
- block_id nBlkId;
- block_id valBlk[MAX_RECS_PER_BLK]; /* valBlk[j] := value in j-th record of current block */
- unsigned char nLevl;
- cache_rec_ptr_t cr;
- int cycle;
- trans_num tn;
- sm_uc_ptr_t buffaddr;
- unsigned short nRecLen;
- uint4 tmp;
- boolean_t is_mm;
- int4 random;
- int4 rCnt; /* number of entries in valBlk */
- DCL_THREADGBL_ACCESS;
-
- SETUP_THREADGBL_ACCESS;
- is_mm = (dba_mm == cs_data->acc_meth);
- pTarg = gv_target;
- pTargHist = &gv_target->hist;
- /* The following largely mimics gvcst_search/gvcst_search_blk */
- nBlkId = pTarg->root;
- tn = cs_addrs->ti->curr_tn;
- if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&cycle, &cr)))
- return (enum cdb_sc)rdfail_detail;
- nLevl = ((blk_hdr_ptr_t)pBlkBase)->levl;
- if (MAX_BT_DEPTH < (int)nLevl)
- {
- assert(CDB_STAGNATE > t_tries);
- return cdb_sc_maxlvl;
- }
- if (0 == (int)nLevl)
- {
- assert(CDB_STAGNATE > t_tries);
- return cdb_sc_badlvl;
- }
- pTargHist->depth = (int)nLevl;
- pCurr = &pTargHist->h[nLevl];
- (pCurr + 1)->blk_num = 0;
- pCurr->tn = tn;
- pCurr->cycle = cycle;
- pCurr->cr = cr;
- for (;;)
- {
- assert(pCurr->level == nLevl);
- pCurr->cse = NULL;
- pCurr->blk_num = nBlkId;
- pCurr->buffaddr = pBlkBase;
- for ( rCnt = 0, pRec = pBlkBase + SIZEOF(blk_hdr), pTop = pBlkBase + ((blk_hdr_ptr_t)pBlkBase)->bsiz;
- pRec != pTop && rCnt < MAX_RECS_PER_BLK;
- rCnt++, pRec += nRecLen )
- { /* enumerate records in block */
- GET_USHORT(nRecLen, &((rec_hdr_ptr_t)pRec)->rsiz);
- pVal = pRec + nRecLen - SIZEOF(block_id);
- if (nRecLen == 0)
- {
- assert(CDB_STAGNATE > t_tries);
- return cdb_sc_badoffset;
- }
- if (pRec + nRecLen > pTop)
- {
- assert(CDB_STAGNATE > t_tries);
- return cdb_sc_blklenerr;
- }
- GET_LONG(tmp, pVal);
- valBlk[rCnt] = tmp;
- }
- r[nLevl] = rCnt;
- /* randomly select next block */
- random = (int4)(rCnt * drand48());
- random = random & 0x7fffffff; /* to make sure that the sign bit(msb) is off */
- nBlkId = valBlk[random];
- if (is_mm && (nBlkId > cs_addrs->total_blks))
- {
- if (cs_addrs->total_blks < cs_addrs->ti->total_blks)
- return cdb_sc_helpedout;
- else
- return cdb_sc_blknumerr;
- }
- --pCurr; --nLevl;
- if (nLevl < 1)
- break;
- pCurr->tn = cs_addrs->ti->curr_tn;
- if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&pCurr->cycle, &pCurr->cr)))
- return (enum cdb_sc)rdfail_detail;
- if (((blk_hdr_ptr_t)pBlkBase)->levl != nLevl)
- {
- assert(CDB_STAGNATE > t_tries);
- return cdb_sc_badlvl;
- }
- }
- return cdb_sc_normal;
-}
diff --git a/sr_unix/mu_size_impsample.c b/sr_unix/mu_size_impsample.c
index ce02343..6f3de6f 100644
--- a/sr_unix/mu_size_impsample.c
+++ b/sr_unix/mu_size_impsample.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012, 2013 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,15 +21,12 @@
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
-#include "jnl.h"
#include "gdsblkops.h"
#include "gdskill.h"
#include "gdscc.h"
-#include "copy.h"
#include "interlock.h"
#include "muextr.h"
#include "mu_reorg.h"
-
/* Include prototypes */
#include "t_end.h"
#include "t_retry.h"
@@ -47,11 +44,9 @@
#include "wcs_sleep.h"
#include "memcoherency.h"
#include "change_reg.h"
-
#include "gtm_time.h"
#include "mvalconv.h"
-#include "t_qread.h"
-#include "longset.h" /* needed for cws_insert.h */
+#include "longset.h" /* needed for cws_insert.h */
#include "hashtab_int4.h"
#include "cws_insert.h"
#include <math.h>
@@ -62,24 +57,23 @@ error_def(ERR_MUSIZEFAIL);
GBLREF bool mu_ctrlc_occurred;
GBLREF bool mu_ctrly_occurred;
GBLREF gv_namehead *gv_target;
-GBLREF unsigned int t_tries;
+GBLREF inctn_opcode_t inctn_opcode;
+GBLREF int muint_adj;
+GBLREF int4 mu_int_adj[];
GBLREF int4 process_id;
-GBLREF inctn_opcode_t inctn_opcode;
+GBLREF unsigned int t_tries;
#define MAX_RECS_PER_BLK 65535
#define MAX_RELIABLE 10000 /* Used to tweak the error estimates */
-#define EPS 1e-6
-#define SQR(X) ((double)(X) * (double)(X))
-#define ROUND(X) ((int)((X) + 0.5)) /* c89 does not have round() and some Solaris machines uses that compiler */
typedef struct
{ /* cumulative stats */
int4 n; /* number of samples */
double W[MAX_BT_DEPTH + 1]; /* Sum of the importance values of samples for each depth level */
double w_mu[MAX_BT_DEPTH + 1]; /* The mean of importance values. It is used to calculate w_variance */
- double w_variance[MAX_BT_DEPTH + 1];/* The variance of importance values. It is used to calculate effective sample size */
+ double w_variance[MAX_BT_DEPTH + 1]; /* The variance of importance values; used to calculate effective sample size */
double mu[MAX_BT_DEPTH + 1]; /* mu[j] := mean of weighted r[j]'s over previous n traversals.
- It is the expected number of records at depth j
+ * It is the expected number of records at depth j
* Note: mu_n = mu_{n-1} + w_n/W_n*(r_n - M_{n-1})
*/
double S[MAX_BT_DEPTH + 1]; /* S[j] := sum of w_i*(r_i[j] - M[j])^2 over previous traversals.
@@ -88,7 +82,9 @@ typedef struct
* Subsequently they are divided by the effective sample size to give the variance
* of the mean
*/
+ double A[MAX_BT_DEPTH + 1]; /* A[j] := mean of a[j] over previous n traversals]; see note on mu */
/* Final estimates */
+ double AT; /* estimated total adjacency */
double blktot[MAX_BT_DEPTH + 1]; /* estimated #blocks at each level */
double blkerr[MAX_BT_DEPTH + 1]; /* approximate variance of blktot */
double rectot[MAX_BT_DEPTH + 1]; /* estimated #records at each level */
@@ -97,62 +93,51 @@ typedef struct
double R; /* estimated total records */
} stat_t;
-STATICFNDCL void clear_vector_impsmpl(double *v);
-STATICFNDCL void init_stats_impsmpl(stat_t *stat);
STATICFNDCL void finalize_stats_impsmpl(stat_t *stat);
-STATICFNDCL void accum_stats_impsmpl(stat_t *stat, double *r);
+STATICFNDCL void accum_stats_impsmpl(stat_t *stat, double *r, double *a);
-STATICFNDEF void clear_vector_impsmpl(double *v)
-{
- int j;
- for (j = 0; j <= MAX_BT_DEPTH; j++)
- v[j] = 0;
+/* macro makes it convenient to manange initialization with changes to stat_t */
+#define INIT_STATS(stat) \
+{ \
+ stat.n = 0; \
+ CLEAR_VECTOR(stat.W); \
+ CLEAR_VECTOR(stat.w_mu); \
+ CLEAR_VECTOR(stat.w_variance); \
+ CLEAR_VECTOR(stat.mu); \
+ CLEAR_VECTOR(stat.S); \
+ CLEAR_VECTOR(stat.blktot); \
+ CLEAR_VECTOR(stat.blkerr); \
+ CLEAR_VECTOR(stat.rectot); \
+ CLEAR_VECTOR(stat.A); \
}
-
-STATICFNDEF void init_stats_impsmpl(stat_t *stat)
-{
- stat->n = 0;
- clear_vector_impsmpl(stat->W);
- clear_vector_impsmpl(stat->w_mu);
- clear_vector_impsmpl(stat->w_variance);
- clear_vector_impsmpl(stat->mu);
- clear_vector_impsmpl(stat->S);
- clear_vector_impsmpl(stat->blktot);
- clear_vector_impsmpl(stat->blkerr);
- clear_vector_impsmpl(stat->rectot);
-}
-
-/*
- * Importance Sampling
- */
+ /* Importance Sampling */
int4 mu_size_impsample(glist *gl_ptr, int4 M, int4 seed)
{
+ boolean_t tn_aborted;
+ double a[MAX_BT_DEPTH + 1]; /* a[j] is # of adjacent block pointers in level j block of cur traversal */
+ double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */
enum cdb_sc status;
- trans_num ret_tn;
int k, h;
- boolean_t verify_reads;
- boolean_t tn_aborted;
+ stat_t rstat;
+ trans_num ret_tn;
unsigned int lcl_t_tries;
- double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */
- stat_t rstat, ustat;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
inctn_opcode = inctn_invalid_op;
+ /* set gv_target/gv_currkey/gv_cur_region/cs_addrs/cs_data to correspond to <globalname,reg> in gl_ptr */
DO_OP_GVNAME(gl_ptr);
- /* sets gv_target/gv_currkey/gv_cur_region/cs_addrs/cs_data to correspond to <globalname,reg> in gl_ptr */
if (0 == gv_target->root)
- { /* Global does not exist (online rollback). Not an error. */
- gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_GBLNOEXIST, 2, GNAME(gl_ptr).len, GNAME(gl_ptr).addr);
- return EXIT_NRM;
- }
+ { /* Global does not exist (online rollback). Not an error. */
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_GBLNOEXIST, 2, GNAME(gl_ptr).len, GNAME(gl_ptr).addr);
+ return EXIT_NRM;
+ }
if (!seed)
seed = (int4)(time(0) * process_id);
srand48(seed);
-
/* do M random traversals */
- init_stats_impsmpl(&rstat);
+ INIT_STATS(rstat);
for (k = 1; k <= M; k++)
{
if (mu_ctrlc_occurred || mu_ctrly_occurred)
@@ -160,17 +145,18 @@ int4 mu_size_impsample(glist *gl_ptr, int4 M, int4 seed)
t_begin(ERR_MUSIZEFAIL, 0);
for (;;)
{
- clear_vector_impsmpl(r);
- if (cdb_sc_normal != (status = rand_traverse(r)))
+ CLEAR_VECTOR(r);
+ CLEAR_VECTOR(a);
+ if (cdb_sc_normal != (status = mu_size_rand_traverse(r, a))) /* WARNING: assignment */
{
assert(CDB_STAGNATE > t_tries);
t_retry(status);
continue;
}
gv_target->clue.end = 0;
- gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */
+ gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */
DEBUG_ONLY(lcl_t_tries = t_tries);
- if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED)))
+ if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED))) /* WARNING: assignment */
{
ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted);
if (tn_aborted)
@@ -181,104 +167,99 @@ int4 mu_size_impsample(glist *gl_ptr, int4 M, int4 seed)
}
continue;
}
- accum_stats_impsmpl(&rstat, r);
+ accum_stats_impsmpl(&rstat, r, a);
break;
}
}
finalize_stats_impsmpl(&rstat);
-
/* display rstat data
* Showing the error as 2 standard deviations which is a 95% confidence interval for the
* mean number of blocks at each level
*/
util_out_print("Number of generated samples = !UL", FLUSH, rstat.n);
- util_out_print("Level Blocks 2 sigma(+/-)", FLUSH);
- for (h = MAX_BT_DEPTH; (h >= 0) && (rstat.blktot[h] < EPS); h--);
+ util_out_print("Level Blocks Adjacent 2 sigma(+/-)", FLUSH);
+ for (h = MAX_BT_DEPTH; (0 <= h) && (rstat.blktot[h] < EPS); h--);
for ( ; h > 0; h--)
- util_out_print("!5UL !15UL !15UL ~ !3UL%", FLUSH, h, (int)ROUND(rstat.blktot[h]),
- (int)ROUND(sqrt(rstat.blkerr[h])*2),
- (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0)
+ util_out_print("!5UL !15UL !15UL !15UL ~ !3UL%", FLUSH, h, (int)ROUND(rstat.blktot[h]),
+ (int)ROUND(mu_int_adj[h]),
+ (int)ROUND(sqrt(rstat.blkerr[h]) * 2),
+ (int)ROUND(sqrt(rstat.blkerr[h]) * 2 / rstat.blktot[h] * 100.0)
);
- util_out_print("!5UL !15UL !15UL ~ !3UL%", FLUSH, h, (int)ROUND(rstat.blktot[h]),
- (int)ROUND(sqrt(rstat.blkerr[h])*2),
- (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0)
+ util_out_print("!5UL !15UL !15UL !15UL ~ !3UL%", FLUSH, h, (int)ROUND(rstat.blktot[h]),
+ (int)ROUND(mu_int_adj[h]),
+ (int)ROUND(sqrt(rstat.blkerr[h]) * 2),
+ (int)ROUND(sqrt(rstat.blkerr[h]) * 2 / rstat.blktot[h] * 100.0)
);
- util_out_print("Total !15UL !15UL ~ !3UL%", FLUSH, (int)ROUND(rstat.B),
- (int)ROUND(sqrt(rstat.error)*2),
- (int)ROUND(sqrt(rstat.error)*2/rstat.B*100.0)
+ util_out_print("Total !15UL !15UL !15UL ~ !3UL%", FLUSH, (int)ROUND(rstat.B),
+ (int)ROUND(rstat.AT),
+ (int)ROUND(sqrt(rstat.error) * 2),
+ (int)ROUND(sqrt(rstat.error) * 2 / rstat.B * 100.0)
);
-
return EXIT_NRM;
}
-
-STATICFNDEF void accum_stats_impsmpl(stat_t *stat, double *r)
+STATICFNDEF void accum_stats_impsmpl(stat_t *stat, double *r, double *a)
{
- int l, root_level, n;
- double mu0, w_mu0, w[MAX_BT_DEPTH + 1] /* importance */;
+ double mu0, w_mu0, w[MAX_BT_DEPTH + 1] /* importance */;
+ int k, l, root_level;
++stat->n;
- for (l = MAX_BT_DEPTH; (l >= 0) && (r[l] < EPS); l--)
+ for (l = MAX_BT_DEPTH; (0 <= l) && (r[l] < EPS); l--)
w[l] = 0;
root_level = l;
- assert(root_level >= 0);
+ assert(0 <= root_level);
w[root_level] = 1;
- for (l = root_level - 1; l >= 1; l--)
- w[l] = w[l + 1] * r[l + 1]; /* TODO consider using log to avoid overflow if it becomes an issue */
+ for (k = l - 1; 2 <= l; k--, l--)
+ w[k] = w[l] * r[l]; /* NOTE: consider using log to avoid overflow if it becomes an issue */
w[0] = 0; /* computing #blks (e.g #recs in lvl 1+), not #recs in lvl 0+ */
-
for (l = 1; l <= root_level; l++)
{
stat->W[l] += w[l];
w_mu0 = stat->w_mu[l];
- stat->w_mu[l] += (w[l] - stat->w_mu[l])/stat->n;
- stat->w_variance[l] += (w[l] - stat->w_mu[l])*(w[l] - w_mu0);
+ stat->w_mu[l] += (w[l] - w_mu0) / stat->n;
+ stat->w_variance[l] += (w[l] - stat->w_mu[l]) * (w[l] - w_mu0);
mu0 = stat->mu[l];
- stat->mu[l] += w[l]/stat->W[l]*(r[l] - stat->mu[l]);
- stat->S[l] += w[l]*(r[l] - stat->mu[l])*(r[l] - mu0);
+ stat->mu[l] += (w[l] / stat->W[l] * (r[l] - stat->mu[l]));
+ stat->S[l] += (w[l] * (r[l] - stat->mu[l]) * (r[l] - mu0));
+ stat->A[l] += (w[l] / stat->W[l] * (a[l] - stat->A[l]));
}
}
-
STATICFNDEF void finalize_stats_impsmpl(stat_t *stat)
{
- int h;
- double ess; /* effective sample size */
+ double ess; /* effective sample size */
+ int k, l;
- for (h = 1; h <= MAX_BT_DEPTH; h++)
- if (stat->W[h] > 0)
+ for (l = 1; MAX_BT_DEPTH >= l; l++)
+ if (stat->W[l] > 0)
{
/* ess = n / ( 1 + Var( w/mu(w) ) ).
- * This comes from effective sample size for importance sampling in the literature*/
- ess = stat->n / ( 1 + (stat->w_variance[h]/stat->n)/SQR(stat->w_mu[h]) );
+ * This comes from effective sample size for importance sampling in the literature
+ */
+ ess = stat->n / ( 1 + (stat->w_variance[l] / stat->n) / SQR(stat->w_mu[l]) );
/* Variance of the mean (mean referes to avg number of records per block) is
- * Var(R)/N where N is effective sample size */
- stat->S[h] /= stat->W[h];
- stat->S[h] /= (ess + 1);
+ * Var(R)/N where N is effective sample size
+ */
+ stat->S[l] /= stat->W[l];
+ stat->S[l] /= (ess + 1);
}
stat->W[0] = stat->n; /* for arithmetic below */
- for (h = MAX_BT_DEPTH; (h >= 0) && (stat->mu[h] < EPS); h--);
- assert(h >= 0); /* stat->mu[0] should remain zero */
- stat->blktot[h] = 1;
- stat->blkerr[h] = 0;
- for (h-- ; h >= 0; h--)
+ for (l = MAX_BT_DEPTH; (0 <= l) && (stat->mu[l] < EPS); l--)
+ ;
+ assert(0 <= l); /* stat->mu[0] should remain zero */
+ stat->AT = stat->blkerr[l] = stat->error = stat->R = 0;
+ stat->B = stat->blktot[l] = 1;
+ for (k = l - 1 ; 0 < l; k--, l--)
{
- stat->blktot[h] = stat->blktot[h + 1] * stat->mu[h + 1];
+ stat->blktot[k] = stat->blktot[l] * stat->mu[l];
/* Var(XY) assuming X and Y are independent = E[X]^2*Var(Y) + E[Y]^2*Var(X) + Var(X)*Var(Y) */
- stat->blkerr[h] = SQR(stat->mu[h + 1])*stat->blkerr[h + 1] + SQR(stat->blktot[h + 1])*stat->S[h + 1]
- + stat->blkerr[h + 1]*stat->S[h + 1];
- }
- stat->B = 0;
- stat->error = 0;
- for (h = 0; h <= MAX_BT_DEPTH; h++)
- {
- stat->B += stat->blktot[h];
- stat->error += stat->blkerr[h];
- }
- stat->R = 0;
- for (h = 0; h <= MAX_BT_DEPTH; h++)
- {
- stat->rectot[h] = stat->blktot[h] * stat->mu[h];
- stat->R += stat->rectot[h];
+ stat->blkerr[k] = SQR(stat->mu[l]) * stat->blkerr[l] + SQR(stat->blktot[l]) * stat->S[l]
+ + stat->blkerr[l] * stat->S[l];
+ stat->B += stat->blktot[k];
+ mu_int_adj[k] = stat->blktot[l] * stat->A[l];
+ stat->AT += mu_int_adj[k];
+ stat->error += stat->blkerr[k];
+ stat->rectot[k] = stat->blktot[k] * stat->mu[k];
+ stat->R += stat->rectot[k];
}
}
diff --git a/sr_unix/mu_size_scan.c b/sr_unix/mu_size_scan.c
index 5602c6c..4ff8a13 100644
--- a/sr_unix/mu_size_scan.c
+++ b/sr_unix/mu_size_scan.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012, 2013 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,14 +21,13 @@
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
-#include "jnl.h"
#include "gdsblkops.h"
#include "gdskill.h"
#include "gdscc.h"
#include "copy.h"
#include "interlock.h"
#include "muextr.h"
-
+#include "mupint.h"
/* Include prototypes */
#include "t_end.h"
#include "t_retry.h"
@@ -46,14 +45,12 @@
#include "wcs_sleep.h"
#include "memcoherency.h"
#include "change_reg.h"
-
#include "gtm_time.h"
#include "mvalconv.h"
#include "t_qread.h"
#include "longset.h" /* needed for cws_insert.h */
#include "hashtab_int4.h"
#include "cws_insert.h"
-#include "min_max.h"
#include <math.h>
error_def(ERR_GBLNOEXIST);
@@ -62,73 +59,41 @@ error_def(ERR_MUSIZEINVARG);
GBLREF bool mu_ctrlc_occurred;
GBLREF bool mu_ctrly_occurred;
+GBLREF gv_namehead *gv_target;
+GBLREF int4 process_id;
+GBLREF inctn_opcode_t inctn_opcode;
+GBLREF unsigned char rdfail_detail;
+GBLREF int4 mu_int_adj[];
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
-GBLREF gv_namehead *gv_target;
GBLREF unsigned int t_tries;
-GBLREF int4 process_id;
-GBLREF inctn_opcode_t inctn_opcode;
-GBLREF unsigned char rdfail_detail;
-GBLDEF uint4 total_recs;
-GBLDEF uint4 total_scans;
-GBLDEF int targ_levl;
-GBLDEF INTPTR_T saveoff[MAX_BT_DEPTH + 1];
+STATICDEF int targ_levl;
+STATICDEF uint4 total_recs, total_scans;
+STATICDEF INTPTR_T saveoff[MAX_BT_DEPTH + 1];
+
+STATICFNDCL enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skiprecs);
+STATICFNDCL enum cdb_sc read_block(block_id nBlkId, sm_uc_ptr_t *pBlkBase_ptr, int *nLevl_ptr, int desired_levl);
#define ANY_ROOT_LEVL (MAX_BT_DEPTH + 5) /* overload invalid level value */
-#define MAX_RECS_PER_BLK 65535
#define MAX_SCANS 200000000 /* catch infinite loops */
-#define GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop) \
-{ \
- status = cdb_sc_normal; \
- GET_USHORT(nRecLen, &((rec_hdr_ptr_t)pRec)->rsiz); \
- if (nRecLen == 0) \
- status = cdb_sc_badoffset; \
- else if (pRec + nRecLen > pTop) \
- status = cdb_sc_blklenerr; \
-}
-
-#define GET_AND_CHECK_LEVL(status, nLevl, desired_levl, pBlkBase) \
-{ \
- status = cdb_sc_normal; \
- nLevl = ((blk_hdr_ptr_t)pBlkBase)->levl; \
- if (MAX_BT_DEPTH < (int)nLevl) \
- status = cdb_sc_maxlvl; \
- else if (ANY_ROOT_LEVL == desired_levl) \
- { \
- if (0 == (int)nLevl) \
- status = cdb_sc_badlvl; \
- } else if (desired_levl !=(int)nLevl) \
- status = cdb_sc_badlvl; \
-}
-
-#define BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen) for (pTop = pBlkBase + ((blk_hdr_ptr_t)pBlkBase)->bsiz, \
- pRec = pBlkBase + SIZEOF(blk_hdr), i = 0; \
- i < MAX_RECS_PER_BLK && (pRec != pTop); i++, pRec += nRecLen)
-
-enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skiprecs);
-enum cdb_sc read_block(block_id nBlkId, sm_uc_ptr_t *pBlkBase_ptr, int *nLevl_ptr, int desired_levl);
-
int4 mu_size_scan(glist *gl_ptr, int4 level)
{
+ block_id nBlkId;
+ boolean_t equal, tn_aborted, verify_reads;
enum cdb_sc status;
trans_num ret_tn;
- int k, h;
- boolean_t verify_reads;
- boolean_t tn_aborted;
- boolean_t equal;
- unsigned int lcl_t_tries;
- block_id nBlkId;
+ int h, i, k;
int4 nLevl;
sm_uc_ptr_t pBlkBase;
- int i;
+ unsigned int lcl_t_tries;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
inctn_opcode = inctn_invalid_op;
+ /* set gv_target/gv_currkey/gv_cur_region/cs_addrs/cs_data to correspond to <globalname,reg> in gl_ptr */
DO_OP_GVNAME(gl_ptr);
- /* sets gv_target/gv_currkey/gv_cur_region/cs_addrs/cs_data to correspond to <globalname,reg> in gl_ptr */
if (0 == gv_target->root)
{ /* Global does not exist (online rollback). Not an error. */
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_GBLNOEXIST, 2, GNAME(gl_ptr).len, GNAME(gl_ptr).addr);
@@ -143,7 +108,8 @@ int4 mu_size_scan(glist *gl_ptr, int4 level)
}
targ_levl = 0;
/* Read the root block and convert negative levels to positive. Negative levels are defined to be counted from root with
- * -1 being children of root */
+ * -1 identifying the children of root
+ */
t_begin(ERR_MUSIZEFAIL, 0);
for(;;)
{ /* retry loop */
@@ -207,8 +173,8 @@ int4 mu_size_scan(glist *gl_ptr, int4 level)
}
break;
}
- util_out_print("Level Blocks Records", FLUSH);
- util_out_print("!5UL !15UL !16UL", FLUSH, level, total_scans, total_recs);
+ util_out_print("Level Blocks Records Adjacent", FLUSH);
+ util_out_print("!5UL !15UL !16UL !16UL", FLUSH, level, total_scans, total_recs, mu_int_adj[level ? level : 1]);
if (mu_ctrlc_occurred || mu_ctrly_occurred)
return EXIT_ERR;
return EXIT_NRM;
@@ -216,40 +182,40 @@ int4 mu_size_scan(glist *gl_ptr, int4 level)
enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skiprecs)
{
- int incr_recs = 0, incr_scans = 0;
- boolean_t first_iter, last_rec, next_endtree, next_skiprecs;
- trans_num ret_tn;
- sm_uc_ptr_t pVal, pTop, pRec, child_pBlkBase;
- int4 child_nLevl;
- unsigned short nRecLen;
- int4 i;
- enum cdb_sc status;
block_id nBlkId;
- int curroff;
+ boolean_t next_endtree, first_iter, last_rec, next_skiprecs;
cache_rec_ptr_t cr;
+ enum cdb_sc status;
+ int curroff, incr_recs = 0, incr_scans = 0;
+ int4 child_nLevl, i, rCnt;
+ sm_uc_ptr_t pTop, pRec, child_pBlkBase;
srch_hist sibhist;
+ trans_num ret_tn;
+ unsigned short nRecLen;
assert(total_scans < MAX_SCANS);
if (lvl == targ_levl)
{ /* reached the bottom. count records in this block and validate */
- BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen)
+ BLK_LOOP(rCnt, pRec, pBlkBase, pTop, nRecLen)
{
- GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop);
+ GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop, nBlkId);
if (cdb_sc_normal != status)
{
assert(CDB_STAGNATE > t_tries);
return status;
}
+ if (lvl)
+ CHECK_ADJACENCY(nBlkId, lvl, mu_int_adj[lvl]);
}
- incr_recs = i;
+ incr_recs = rCnt;
incr_scans = 1;
} else if (lvl > targ_levl)
{ /* visit each child */
first_iter = TRUE;
gv_target->hist.h[lvl - targ_levl].curr_rec.offset = saveoff[lvl];
- BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen)
+ BLK_LOOP(rCnt, pRec, pBlkBase, pTop, nRecLen)
{
- GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop);
+ GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop, nBlkId);
if (cdb_sc_normal != status)
{
assert(CDB_STAGNATE > t_tries);
@@ -259,8 +225,6 @@ enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skip
gv_target->hist.h[lvl - targ_levl].curr_rec.offset = curroff;
if (skiprecs && (curroff < saveoff[lvl]))
continue; /* skip these guys, we've already counted over there */
- pVal = pRec + nRecLen - SIZEOF(block_id);
- GET_LONG(nBlkId, pVal);
status = read_block(nBlkId, &child_pBlkBase, &child_nLevl, lvl - 1);
if (status != cdb_sc_normal)
{
@@ -305,15 +269,14 @@ enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skip
enum cdb_sc read_block(block_id nBlkId, sm_uc_ptr_t *pBlkBase_ptr, int *nLevl_ptr, int desired_levl)
{
- sm_uc_ptr_t pBlkBase;
+ cache_rec_ptr_t cr;
+ enum cdb_sc status;
+ int cycle, i;
register srch_blk_status *pCurr;
register srch_hist *pTargHist;
- unsigned char nLevl;
- cache_rec_ptr_t cr;
- int cycle;
+ sm_uc_ptr_t pBlkBase;
trans_num tn;
- enum cdb_sc status;
- int i;
+ unsigned char nLevl;
pTargHist = &gv_target->hist;
tn = cs_addrs->ti->curr_tn;
diff --git a/sr_unix/mubgetfil.c b/sr_unix/mubgetfil.c
index 0ce2127..01fc11a 100644
--- a/sr_unix/mubgetfil.c
+++ b/sr_unix/mubgetfil.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -34,17 +34,15 @@
#include "gtm_caseconv.h"
#include "mupip_exit.h"
-GBLREF mstr directory;
-GBLREF bool is_directory;
-GBLREF bool error_mupip;
GBLREF backup_reg_list *mu_repl_inst_reg_list;
+GBLREF boolean_t is_directory;
+GBLREF mstr directory;
-bool mubgetfil(backup_reg_list *list, char *name, unsigned short len)
+boolean_t mubgetfil(backup_reg_list *list, char *name, unsigned short len)
{
- struct stat stat_buf;
+ char tcp[5], temp;
int stat_res;
- char temp;
- char tcp[5];
+ struct stat stat_buf;
if (0 == len)
return FALSE;
diff --git a/sr_unix/mumps_clitab.c b/sr_unix/mumps_clitab.c
index 28533de..21551f8 100644
--- a/sr_unix/mumps_clitab.c
+++ b/sr_unix/mumps_clitab.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -31,6 +31,7 @@ static readonly CLI_ENTRY mumps_qual[] = {
{ "DEBUG", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NON_NEG, VAL_N_A, 0},
{ "DIRECT_MODE", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NON_NEG, VAL_N_A, 0},
{ "DYNAMIC_LITERALS", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NEG, VAL_N_A, 0},
+{ "EMBED_SOURCE", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NEG, VAL_N_A, 0},
{ "IGNORE", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NEG, VAL_N_A, 0},
{ "INLINE_LITERALS", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NEG, VAL_N_A, 0},
{ "LABELS", 0, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_STR, 0},
diff --git a/sr_unix/mupip.c b/sr_unix/mupip.c
index 307163b..478cef9 100644
--- a/sr_unix/mupip.c
+++ b/sr_unix/mupip.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,13 +40,10 @@
#include "stp_parms.h"
#include "stringpool.h"
#include "cli.h"
-#include "gt_timer.h"
#include "io.h"
#include "mupip_exit.h"
-#include "getjobnum.h"
#include "patcode.h"
#include "lke.h"
-#include "get_page_size.h"
#include "gtm_startup_chk.h"
#include "generic_signal_handler.h"
#include "init_secshr_addrs.h"
@@ -56,12 +53,11 @@
#include "mu_term_setup.h"
#include "sig_init.h"
#include "gtmmsg.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
#include "suspsigs_handler.h"
#include "startup.h"
#include "gtm_startup.h"
#include "invocation_mode.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
#include "continue_handler.h"
@@ -91,11 +87,8 @@ int main (int argc, char **argv)
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- set_blocksig();
- gtm_imagetype_init(MUPIP_IMAGE);
+ common_startup_init(MUPIP_IMAGE);
invocation_mode = MUMPS_UTILTRIGR;
- gtm_wcswidth_fnptr = gtm_wcswidth;
- gtm_env_init(); /* read in all environment variables */
err_init(util_base_ch);
UNICODE_ONLY(gtm_strToTitle_ptr = >m_strToTitle);
GTM_ICU_INIT_IF_NEEDED; /* Note: should be invoked after err_init (since it may error out) and before CLI parsing */
@@ -129,6 +122,7 @@ int main (int argc, char **argv)
display_prompt();
}
mupip_exit(SS_NORMAL);
+ return 0;
}
void display_prompt(void)
diff --git a/sr_unix/mupip_cmd.c b/sr_unix/mupip_cmd.c
index e2404a0..a4b03b0 100644
--- a/sr_unix/mupip_cmd.c
+++ b/sr_unix/mupip_cmd.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -136,6 +136,13 @@ static CLI_ENTRY mup_load_fmt_qual[] = {
{ 0 }
};
+static CLI_ENTRY mup_load_onerror_qual[] = {
+ { "INTERACTIVE", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NEG, VAL_N_A, 0 },
+ { "PROCEED", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NEG, VAL_N_A, 0 },
+ { "STOP", 0, 0, 0, 0, 0, DEFA_PRESENT, VAL_DISALLOWED, 0, NEG, VAL_N_A, 0 },
+ { 0 }
+};
+
static CLI_ENTRY mup_jnl_fences_qual[] = {
{ "ALWAYS", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NON_NEG, VAL_N_A, 0 },
{ "NONE", 0, 0, 0, 0, 0, 0, VAL_DISALLOWED, 0, NON_NEG, VAL_N_A, 0 },
@@ -228,8 +235,9 @@ static CLI_ENTRY mup_extend_qual[] = {
};
static CLI_PARM mup_extract_parm[] = {
- { "FILE", "Output File: ", PARM_REQ},
- { "", "", PARM_REQ}
+ { "FILE", "Output File: ", PARM_REQ},
+ { "REGION", "Region(s): " , PARM_REQ},
+ { "", "", PARM_REQ}
};
static readonly CLI_PARM mup_extr_label_parm[] = {
@@ -241,6 +249,7 @@ static CLI_ENTRY mup_extract_qual[] = {
{ "FREEZE", mu_extract, 0, 0, 0, 0, 0, VAL_DISALLOWED, 1, NON_NEG, VAL_N_A, 0 },
{ "LABEL", mu_extract, 0, mup_extr_label_parm, 0, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_STR, 0 },
{ "LOG", mu_extract, 0, 0, 0, 0, 0, VAL_DISALLOWED, 1, NEG, VAL_N_A, 0 },
+ { "REGION", mu_extract, 0, 0, 0, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_N_A, 0 },
{ "SELECT", mu_extract, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_STR, 0 },
{ "STDOUT", mu_extract, 0, 0, 0, 0, 0, VAL_DISALLOWED, 1, NON_NEG, VAL_N_A, 0 },
{ "OCHSET", mu_extract, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_STR, 0 },
@@ -392,13 +401,18 @@ static readonly CLI_PARM mup_load_fmt_parm[] = {
{ "FORMAT", "GO", PARM_REQ}
};
+static readonly CLI_PARM mup_load_onerror_parm[] = {
+ { "ONERROR", "PROCEED", PARM_REQ}
+};
+
static CLI_ENTRY mup_load_qual[] = {
- { "BEGIN", mupip_cvtgbl, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_NUM, 0 },
- { "BLOCK_DENSITY", mupip_cvtgbl, 0, 0, 0, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_NUM, 0 },
- { "END", mupip_cvtgbl, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_NUM, 0 },
- { "FILL_FACTOR", mupip_cvtgbl, 0, mup_load_ff_parm, 0, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_NUM, 0 },
- { "FORMAT", mupip_cvtgbl, 0, mup_load_fmt_parm, mup_load_fmt_qual, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_STR, 0 },
- { "STDIN", mupip_cvtgbl, 0, 0, 0, 0, 0, VAL_DISALLOWED, 1, NON_NEG, VAL_N_A, 0 },
+ { "BEGIN", mupip_cvtgbl, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_NUM, 0 },
+ { "BLOCK_DENSITY", mupip_cvtgbl, 0, 0, 0, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_NUM, 0 },
+ { "END", mupip_cvtgbl, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_NUM, 0 },
+ { "FILL_FACTOR", mupip_cvtgbl, 0, mup_load_ff_parm, 0, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_NUM, 0 },
+ { "FORMAT", mupip_cvtgbl, 0, mup_load_fmt_parm, mup_load_fmt_qual, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_STR, 0 },
+ { "ONERROR", mupip_cvtgbl, 0, mup_load_onerror_parm, mup_load_onerror_qual, 0, 0, VAL_NOT_REQ, 1, NON_NEG, VAL_STR, 0 },
+ { "STDIN", mupip_cvtgbl, 0, 0, 0, 0, 0, VAL_DISALLOWED, 1, NON_NEG, VAL_N_A, 0 },
{ 0 }
};
@@ -437,6 +451,7 @@ static CLI_ENTRY mup_size_heuristic_qual[] = {
{ 0 }
};
static CLI_ENTRY mup_size_qual[] = {
+ { "ADJACENCY", 0, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_NUM, 0 },
{ "HEURISTIC", 0, 0, 0, mup_size_heuristic_qual, 0, 0, VAL_REQ, 1, NON_NEG, VAL_STR, 0 },
{ "REGION", 0, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_STR, 0 },
{ "SELECT", 0, 0, 0, 0, 0, 0, VAL_REQ, 1, NON_NEG, VAL_STR, 0 },
diff --git a/sr_unix/mupip_cvtgbl.c b/sr_unix/mupip_cvtgbl.c
index dcd59c8..d3a8a3b 100644
--- a/sr_unix/mupip_cvtgbl.c
+++ b/sr_unix/mupip_cvtgbl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -37,6 +37,7 @@ GBLREF bool mupip_error_occurred;
GBLREF boolean_t is_replicator;
GBLREF boolean_t skip_dbtriggers;
GBLREF mstr sys_input;
+GBLDEF int onerror;
error_def(ERR_MUNOFINISH);
error_def(ERR_MUPCLIERR);
@@ -46,11 +47,14 @@ error_def(ERR_LOADBGSZ2);
error_def(ERR_LOADEDSZ);
error_def(ERR_LOADEDSZ2);
+#define MAX_ONERROR_VALUE_LEN 11 /* PROCEED, STOP, INTERACTIVE are the choices with INTERACTIVE being the maximum */
+#define MAX_FORMAT_VALUE_LEN 6 /* ZWR, BINARY, GO, GOQ are the choices with BINARY being the longest */
+
void mupip_cvtgbl(void)
{
unsigned short fn_len, len;
- char fn[256];
- unsigned char buff[7];
+ char fn[MAX_FN_LEN + 1];
+ unsigned char buff[MAX_ONERROR_VALUE_LEN];
uint4 begin, end;
int i, format;
uint4 cli_status;
@@ -58,9 +62,10 @@ void mupip_cvtgbl(void)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
+ assert(MAX_ONERROR_VALUE_LEN > MAX_FORMAT_VALUE_LEN); /* so the buff[] definition above is good for FORMAT and ONERROR */
/* If an online rollback occurs when we are loading up the database with new globals and takes us back to a prior logical
* state, then we should not continue with the load. The reason being that the application might rely on certain globals to
- * be present before loading others and that property could be voilated if online rollback takes the database back to a
+ * be present before loading others and that property could be violated if online rollback takes the database back to a
* completely different logical state. Set the variable issue_DBROLLEDBACK_anyways that forces the restart logic to issue
* an rts_error the first time it detects an online rollback (that takes the database to a prior logical state).
*/
@@ -123,9 +128,38 @@ void mupip_cvtgbl(void)
} else
gv_fillfactor = MAX_FILLFACTOR;
+ if (cli_present("ONERROR") == CLI_PRESENT)
+ {
+ len = SIZEOF(buff);
+ if (!cli_get_str("ONERROR", (char *)buff, &len))
+ {
+ assert(FALSE);
+ onerror = ONERROR_PROCEED;
+ } else
+ {
+ lower_to_upper(buff, buff, len);
+ if (!memcmp(buff, "STOP", len))
+ onerror = ONERROR_STOP;
+ else if (!memcmp(buff, "PROCEED", len))
+ onerror = ONERROR_PROCEED;
+ else if (!memcmp(buff, "INTERACTIVE", len))
+ {
+ if (isatty(0)) /*if stdin is a terminal*/
+ onerror = ONERROR_INTERACTIVE;
+ else
+ onerror = ONERROR_STOP;
+ } else
+ {
+ util_out_print("Illegal ONERROR parameter for load",TRUE);
+ mupip_exit(ERR_MUPCLIERR);
+ }
+ }
+ } else
+ onerror = ONERROR_PROCEED; /* Default: Proceed on error */
+
if (cli_present("FORMAT") == CLI_PRESENT)
{
- len = SIZEOF("FORMAT");
+ len = SIZEOF(buff);
if (!cli_get_str("FORMAT", (char *)buff, &len))
go_load(begin, end);
else
diff --git a/sr_unix/mupip_endiancvt.c b/sr_unix/mupip_endiancvt.c
index b4da949..e45c494 100644
--- a/sr_unix/mupip_endiancvt.c
+++ b/sr_unix/mupip_endiancvt.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc *
+ * Copyright 2006, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -404,7 +404,7 @@ void mupip_endiancvt(void)
{ /* Database is encrypted. Initialize encryption and setup the keys to be used in later encryption/decryption */
INIT_PROC_ENCRYPTION(NULL, gtmcrypt_errno);
if (0 == gtmcrypt_errno)
- GTMCRYPT_GETKEY(NULL, old_data->encryption_hash, encr_key_handle, gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(NULL, old_data->encryption_hash, encr_key_handle, gtmcrypt_errno);
if (0 != gtmcrypt_errno)
{
GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, gtm_putmsg, n_len, db_name);
diff --git a/sr_unix/mupip_exit_handler.c b/sr_unix/mupip_exit_handler.c
index 92f9929..dd79f22 100644
--- a/sr_unix/mupip_exit_handler.c
+++ b/sr_unix/mupip_exit_handler.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -62,6 +62,8 @@
#include "op.h"
#include "io.h"
#include "gtmsource_srv_latch.h"
+#include "gtmcrypt.h"
+#include "relinkctl.h"
GBLREF boolean_t mupip_jnl_recover;
GBLREF boolean_t need_core;
@@ -122,6 +124,7 @@ void mupip_exit_handler(void)
recvpool.recvpool_ctl = NULL;
}
gv_rundown(); /* also takes care of detaching from the journal pool */
+ relinkctl_rundown(TRUE);
/* Log the exit of replication servers. In case they are exiting abnormally, their log file pointers
* might not be set up. In that case, use "stderr" for logging.
*/
@@ -148,6 +151,7 @@ void mupip_exit_handler(void)
close_repl_logfiles();
print_exit_stats();
io_rundown(RUNDOWN_EXCEPT_STD);
+ GTMCRYPT_CLOSE;
if (need_core && !created_core)
{
++core_in_progress;
diff --git a/sr_unix/mupip_restore.c b/sr_unix/mupip_restore.c
index 7f2c0ac..2131811 100644
--- a/sr_unix/mupip_restore.c
+++ b/sr_unix/mupip_restore.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -463,7 +463,7 @@ void mupip_restore(void)
{
if (is_bkup_file_encrypted)
{
- GTMCRYPT_GETKEY(NULL, bkup_hash, bkup_key_handle, gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(NULL, bkup_hash, bkup_key_handle, gtmcrypt_errno);
if (0 != gtmcrypt_errno)
{
GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, gtm_putmsg, ptr->input_file.len,
@@ -473,7 +473,8 @@ void mupip_restore(void)
}
if (old_data.is_encrypted)
{
- GTMCRYPT_GETKEY(NULL, old_data.encryption_hash, target_key_handle, gtmcrypt_errno);
+ GTMCRYPT_INIT_BOTH_CIPHER_CONTEXTS(NULL, old_data.encryption_hash, target_key_handle,
+ gtmcrypt_errno);
if (0 != gtmcrypt_errno)
{
GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, gtm_putmsg, n_len, db_name);
diff --git a/sr_unix/mupip_rundown.c b/sr_unix/mupip_rundown.c
index 44b5155..d6e7769 100644
--- a/sr_unix/mupip_rundown.c
+++ b/sr_unix/mupip_rundown.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -100,6 +100,7 @@ void mupip_rundown(void)
exit_status = SS_NORMAL;
file = (CLI_PRESENT == cli_present("FILE"));
region = (CLI_PRESENT == cli_present("REGION"));
+ TREF(skip_file_corrupt_check) = TRUE; /* rundown the database even if csd->file_corrupt is TRUE */
arg_present = (0 != TREF(parms_cnt));
if ((file == region) && (TRUE == file))
mupip_exit(ERR_MUQUALINCOMP);
@@ -129,7 +130,7 @@ void mupip_rundown(void)
if (region || file)
{
do_jnlpool_detach = FALSE;
- anticipatory_freeze_available = ANTICIPATORY_FREEZE_AVAILABLE;
+ anticipatory_freeze_available = INST_FREEZE_ON_ERROR_POLICY;
if ((jnlpool_rndwn_required = (region && mu_star_specified)) || anticipatory_freeze_available) /* note:assigmnent */
{
if (DEBUG_ONLY(repl_inst_available = )REPL_INST_AVAILABLE) /* sets replpool_id/full_len; note: assignment */
diff --git a/sr_unix/mupip_size.c b/sr_unix/mupip_size.c
index 5b4d6cc..b52de57 100644
--- a/sr_unix/mupip_size.c
+++ b/sr_unix/mupip_size.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012, 2013 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,6 +18,7 @@
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
+#include "copy.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "gdskill.h"
@@ -32,8 +33,9 @@
#include "jnl.h"
#include "buddy_list.h" /* needed for tp.h */
#include "hashtab_int4.h" /* needed for tp.h */
+#include "t_qread.h"
#include "tp.h"
-
+#include "mupint.h"
/* Prototypes */
#include "mupip_size.h"
#include "targ_alloc.h"
@@ -43,15 +45,21 @@
#include "gtmmsg.h"
#include "mu_getlst.h"
-error_def(ERR_NOSELECT);
-error_def(ERR_MUNOFINISH);
error_def(ERR_MUNOACTION);
+error_def(ERR_MUNOFINISH);
+error_def(ERR_MUPCLIERR);
error_def(ERR_MUSIZEINVARG);
+error_def(ERR_NOSELECT);
-GBLREF tp_region *grlist;
-GBLREF bool error_mupip;
-GBLREF bool mu_ctrlc_occurred;
-GBLREF bool mu_ctrly_occurred;
+GBLREF block_id mu_int_adj_prev[MAX_BT_DEPTH + 1];
+GBLREF bool error_mupip;
+GBLREF bool mu_ctrlc_occurred;
+GBLREF bool mu_ctrly_occurred;
+GBLREF int muint_adj;
+GBLREF int4 mu_int_adj[MAX_BT_DEPTH + 1];
+GBLREF sgmnt_data_ptr_t cs_data;
+GBLREF tp_region *grlist;
+GBLREF unsigned char rdfail_detail;
typedef struct {
enum {arsample, scan, impsample} heuristic;
@@ -70,24 +78,21 @@ STATICFNDCL void mupip_size_check_error(void);
*/
void mupip_size(void)
{
- uint4 status = EXIT_NRM;
- glist gl_head, exclude_gl_head, *gl_ptr;
- /* configuration default values */
- mupip_size_cfg_t mupip_size_cfg = { impsample, 1000, 1, 0 };
- char cli_buff[MAX_LINE];
- int4 reg_max_rec, reg_max_key, reg_max_blk;
- unsigned short n_len;
- char buff[MAX_LINE];
- unsigned short BUFF_LEN = SIZEOF(buff);
- char *p_end; /* used for strtol validation */
boolean_t restrict_reg = FALSE;
-
+ char buff[MAX_LINE], cli_buff[MAX_LINE];
+ char *p_end; /* used for strtol validation */
+ glist exclude_gl_head, gl_head, *gl_ptr;
+ int4 reg_max_rec, reg_max_key, reg_max_blk;
+ mupip_size_cfg_t mupip_size_cfg = { impsample, 1000, 1, 0 }; /* configuration default values */
+ uint4 status = EXIT_NRM;
+ unsigned short BUFF_LEN = SIZEOF(buff), n_len;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
mu_outofband_setup();
error_mupip = FALSE;
-
+ memset(mu_int_adj, 0, ARRAYSIZE(mu_int_adj));
+ memset(mu_int_adj_prev, 0, ARRAYSIZE(mu_int_adj_prev));
/* Region qualifier */
grlist = NULL;
if (CLI_PRESENT == cli_present("REGION"))
@@ -97,7 +102,6 @@ void mupip_size(void)
mu_getlst("REGION", SIZEOF(tp_region)); /* get the parameter corresponding to REGION qualifier */
}
mupip_size_check_error();
-
/* SELECT qualifier */
memset(cli_buff, 0, SIZEOF(cli_buff));
n_len = SIZEOF(cli_buff);
@@ -119,7 +123,16 @@ void mupip_size(void)
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSELECT);
}
mupip_size_check_error();
-
+ if (CLI_PRESENT == cli_present("ADJACENCY"))
+ {
+ assert(SIZEOF(muint_adj) == SIZEOF(int4));
+ if (0 == cli_get_int("ADJACENCY", (int4 *)&muint_adj))
+ {
+ error_mupip = TRUE;
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_MUPCLIERR);
+ }
+ } else
+ muint_adj = DEFAULT_ADJACENCY;
/* HEURISTIC qualifier */
if (cli_present("HEURISTIC.SCAN") == CLI_PRESENT)
{
@@ -168,7 +181,6 @@ void mupip_size(void)
/* else seed will be based on the time */
}
mupip_size_check_error();
-
/* run mupip size on each global */
for (gl_ptr = gl_head.next; gl_ptr; gl_ptr = gl_ptr->next)
{
@@ -180,7 +192,7 @@ void mupip_size(void)
status |= mu_size_scan(gl_ptr, mupip_size_cfg.level);
break;
case arsample:
- status |= mu_size_arsample(gl_ptr, mupip_size_cfg.samples, TRUE, mupip_size_cfg.seed);
+ status |= mu_size_arsample(gl_ptr, mupip_size_cfg.samples, mupip_size_cfg.seed);
break;
case impsample:
status |= mu_size_impsample(gl_ptr, mupip_size_cfg.samples, mupip_size_cfg.seed);
@@ -192,11 +204,9 @@ void mupip_size(void)
if (mu_ctrlc_occurred || mu_ctrly_occurred)
mupip_exit(ERR_MUNOFINISH);
}
-
mupip_exit(status == EXIT_NRM ? SS_NORMAL : ERR_MUNOFINISH);
}
-
STATICDEF void mupip_size_check_error(void)
{
if (error_mupip)
@@ -205,3 +215,93 @@ STATICDEF void mupip_size_check_error(void)
mupip_exit(ERR_MUNOACTION);
}
}
+
+ /* Performs a random traversal for the sampling methods */
+enum cdb_sc mu_size_rand_traverse(double *r, double *a)
+{
+ sm_uc_ptr_t pVal, pTop, pRec, pBlkBase;
+ block_id nBlkId;
+ block_id valBlk[MAX_RECS_PER_BLK]; /* valBlk[j] := value in j-th record of current block */
+ boolean_t is_mm;
+ cache_rec_ptr_t cr;
+ enum cdb_sc status;
+ int cycle;
+ int4 random;
+ int4 rCnt; /* number of entries in valBlk */
+ register gv_namehead *pTarg;
+ register srch_blk_status *pCurr;
+ register srch_hist *pTargHist;
+ trans_num tn;
+ unsigned char nLevl;
+ unsigned short nRecLen;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ is_mm = (dba_mm == cs_data->acc_meth);
+ pTarg = gv_target;
+ pTargHist = &gv_target->hist;
+ /* The following largely mimics gvcst_search/gvcst_search_blk */
+ nBlkId = pTarg->root;
+ tn = cs_addrs->ti->curr_tn;
+ if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&cycle, &cr)))
+ return (enum cdb_sc)rdfail_detail;
+ nLevl = ((blk_hdr_ptr_t)pBlkBase)->levl;
+ if (MAX_BT_DEPTH < (int)nLevl)
+ {
+ assert(CDB_STAGNATE > t_tries);
+ return cdb_sc_maxlvl;
+ }
+ if (0 == (int)nLevl)
+ {
+ assert(CDB_STAGNATE > t_tries);
+ return cdb_sc_badlvl;
+ }
+ pTargHist->depth = (int)nLevl;
+ pCurr = &pTargHist->h[nLevl];
+ (pCurr + 1)->blk_num = 0;
+ pCurr->tn = tn;
+ pCurr->cycle = cycle;
+ pCurr->cr = cr;
+ for (;;)
+ {
+ assert(pCurr->level == nLevl);
+ pCurr->cse = NULL;
+ pCurr->blk_num = nBlkId;
+ pCurr->buffaddr = pBlkBase;
+ BLK_LOOP(rCnt, pRec, pBlkBase, pTop, nRecLen)
+ { /* enumerate records in block */
+ GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop, nBlkId);
+ if (cdb_sc_normal != status)
+ {
+ assert(CDB_STAGNATE > t_tries);
+ return status;
+ }
+ valBlk[rCnt] = nBlkId;
+ CHECK_ADJACENCY(nBlkId, nLevl, a[nLevl]);
+ }
+ r[nLevl] = rCnt;
+ /* randomly select next block */
+ random = (int4)(rCnt * drand48());
+ random = random & 0x7fffffff; /* to make sure that the sign bit(msb) is off */
+ nBlkId = valBlk[random];
+ if (is_mm && (nBlkId > cs_addrs->total_blks))
+ {
+ if (cs_addrs->total_blks < cs_addrs->ti->total_blks)
+ return cdb_sc_helpedout;
+ else
+ return cdb_sc_blknumerr;
+ }
+ --pCurr; --nLevl;
+ if (nLevl < 1)
+ break;
+ pCurr->tn = cs_addrs->ti->curr_tn;
+ if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&pCurr->cycle, &pCurr->cr)))
+ return (enum cdb_sc)rdfail_detail;
+ if (((blk_hdr_ptr_t)pBlkBase)->levl != nLevl)
+ {
+ assert(CDB_STAGNATE > t_tries);
+ return cdb_sc_badlvl;
+ }
+ }
+ return cdb_sc_normal;
+}
diff --git a/sr_unix/mupip_size.h b/sr_unix/mupip_size.h
index b14b079..8aa6a6c 100644
--- a/sr_unix/mupip_size.h
+++ b/sr_unix/mupip_size.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2012, 2013 Fidelity Information Services, Inc *
+ * Copyright 2012, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -15,9 +15,27 @@
#include "cdb_sc.h"
void mupip_size(void);
-int4 mu_size_arsample(glist *gl_ptr, uint M, boolean_t ar, int seed);
+int4 mu_size_arsample(glist *gl_ptr, uint M, int seed);
int4 mu_size_impsample(glist *gl_ptr, int4 M, int4 seed);
int4 mu_size_scan(glist *gl_ptr, int4 level);
-enum cdb_sc rand_traverse(double *r);
+enum cdb_sc mu_size_rand_traverse(double *r, double *a);
+
+#define EPS 1e-6
+#define MAX_RECS_PER_BLK 65535
+#define ROUND(X) ((int)((X) + 0.5)) /* c89 does not have round() and some Solaris machines uses that compiler */
+#define SQR(X) ((double)(X) * (double)(X))
+
+#define BLK_LOOP(rCnt, pRec, pBlkBase, pTop, nRecLen) \
+ for (rCnt = 0, pTop = pBlkBase + ((blk_hdr_ptr_t)pBlkBase)->bsiz, \
+ pRec = pBlkBase + SIZEOF(blk_hdr); \
+ rCnt < MAX_RECS_PER_BLK && (pRec != pTop); rCnt++, pRec += nRecLen)
+
+#define CLEAR_VECTOR(v) \
+{ \
+ int J; \
+ \
+ for (J = 0; MAX_BT_DEPTH >= J; J++) \
+ v[J] = 0; \
+}
#endif
diff --git a/sr_unix/mutex.c b/sr_unix/mutex.c
index 0e706f4..0735558 100644
--- a/sr_unix/mutex.c
+++ b/sr_unix/mutex.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -20,9 +20,9 @@
#include "gtm_unistd.h"
#include "gtm_stdio.h"
#include "gtm_select.h"
+#include "gtm_un.h"
#include <errno.h>
-#include <sys/un.h>
#if defined(__sparc) || defined(__hpux) || defined(__MVS__) || defined(__linux__) || defined(__CYGWIN__)
#include "gtm_limits.h"
#else
@@ -95,7 +95,6 @@
}
GBLREF pid_t process_id;
-GBLREF int process_exiting;
GBLREF uint4 image_count;
GBLREF int num_additional_processors;
#ifdef MUTEX_MSEM_WAKE
@@ -534,14 +533,14 @@ static enum cdb_sc mutex_sleep(sgmnt_addrs *csa, mutex_lock_t mutex_lock_type)
# ifdef MUTEX_MSEM_WAKE
msem_slot = free_slot;
# endif
- if (!process_exiting && (NULL != free_slot) && (mutex_que_entry_ptr_t)INTERLOCK_FAIL != free_slot)
+ if ((NULL != free_slot) && (mutex_que_entry_ptr_t)INTERLOCK_FAIL != free_slot)
{
free_slot->pid = process_id;
free_slot->mutex_wake_instance = mutex_expected_wake_instance;
# ifdef MUTEX_MSEM_WAKE
mutex_wake_msem_ptr = &free_slot->mutex_wake_msem;
- /* this loop makes sure that the msemaphore is locked initially
- * before the process goes to long sleep
+ /* this loop makes sure that the msemaphore is locked initially before the process goes to
+ * long sleep
*/
do
{
@@ -549,22 +548,13 @@ static enum cdb_sc mutex_sleep(sgmnt_addrs *csa, mutex_lock_t mutex_lock_type)
} while (-1 == rc && EINTR == errno);
# endif
/*
- * Significance of mutex_wake_instance field :
- * -----------------------------------------
- * After queueing itself, a process
- * might go to sleep (select call in
- * mutex_long_sleep) awaiting a wakeup message
- * or a timeout. It is possible that a wakeup
- * message might arrive after timeout. In this
- * case, a later attempt at waiting for a
- * wakeup message will falsely succeed on an
- * old wakeup message. We use the
- * mutex_wake_instance field (value 0 or 1)
- * to distinguish between an old and a new
- * wakeup message. Since at any given time
- * there is atmost one entry in the queue for
- * a process, the only values we need for
- * mutex_wake_instance are 0 and 1.
+ * Significance of mutex_wake_instance field : After queueing itself, a process might go to
+ * sleep -select call in mutex_long_sleep- awaiting a wakeup message or a timeout. It is
+ * possible that a wakeup message might arrive after timeout. In this case, a later attempt
+ * at waiting for a wakeup message will falsely succeed on an old wakeup message. We use the
+ * mutex_wake_instance field (value 0 or 1) to distinguish between an old and a new wakeup
+ * message. Since at any given time there is atmost one entry in the queue for a process,
+ * the only values we need for mutex_wake_instance are 0 and 1.
*/
mutex_expected_wake_instance = BIN_TOGGLE(mutex_expected_wake_instance);
quant_retry_counter_insq = QUANT_RETRY;
@@ -574,11 +564,11 @@ static enum cdb_sc mutex_sleep(sgmnt_addrs *csa, mutex_lock_t mutex_lock_type)
do
{
if (INTERLOCK_FAIL !=
- INSQTI((que_ent_ptr_t)free_slot, (que_head_ptr_t)&addr->prochead))
+ INSQTI((que_ent_ptr_t)free_slot, (que_head_ptr_t)&addr->prochead))
{
MUTEX_DPRINT3("%d: Inserted %d into wait queue\n", process_id,
- free_slot->pid);
- return (mutex_long_sleep(addr, mutex_lock_type, csa));
+ free_slot->pid);
+ return mutex_long_sleep(addr, mutex_lock_type, csa);
}
} while (--queue_retry_counter_insq);
if (!(--quant_retry_counter_insq))
@@ -589,33 +579,25 @@ static enum cdb_sc mutex_sleep(sgmnt_addrs *csa, mutex_lock_t mutex_lock_type)
}
if ((mutex_que_entry_ptr_t)INTERLOCK_FAIL == free_slot)
{
- /* secondary interlock failed on an attempt to
- * remove an entry from the free queue */
+ /* secondary interlock failed on an attempt to remove an entry from the free queue */
redo_cntr = 0;
continue;
}
if ((mutex_que_entry_ptr_t)NULL == free_slot)
{
- /* Record queue full event in db file header if applicable.
- * Take care not to do it for jnlpool which has no concept of a db cache.
- * In that case csa->hdr is NULL so use PROBE_BG_TRACE_PRO_ANY macro.
+ /* Record queue full event in db file header if applicable. Take care not to do it for
+ * jnlpool which has no concept of a db cache. In that case csa->hdr is NULL so use
+ * PROBE_BG_TRACE_PRO_ANY macro.
*/
PROBE_BG_TRACE_PRO_ANY(csa, mutex_queue_full);
MUTEX_DPRINT2("%d: Free Queue full\n", process_id);
- /*
- * When I can't find a free slot in the queue
- * repeatedly, it means that there is no
- * progress in the system. A recovery attempt
- * might be warranted in this scenario. The
- * trick is to return cdb_sc_normal which in
- * turn causes another spin-loop initiation (or
- * recovery when implemented).
- * The objective of mutex_sleep is achieved
- * (partially) in that sleep is done, though
- * queueing isn't.
- */
- } else
- assert(process_exiting); /* timers might be off, but this adds CPU load at an awkward time */
+ /* When I can't find a free slot in the queue repeatedly, it means that there is no progress
+ * in the system. A recovery attempt might be warranted in this scenario. The trick is to
+ * return cdb_sc_normal which in turn causes another spin-loop initiation (or recovery when
+ * implemented). The objective of mutex_sleep is achieved (partially) in that sleep is
+ * done, though queueing isn't.
+ */
+ }
MICROSEC_SLEEP(ONE_MILLION - 1); /* Wait a second, then try again */
mutex_deadlock_check(addr, csa);
if (++redo_cntr < MUTEX_MAX_WAIT_FOR_PROGRESS_CNTR)
diff --git a/sr_unix/obj_code.c b/sr_unix/obj_code.c
index ee186eb..935386b 100644
--- a/sr_unix/obj_code.c
+++ b/sr_unix/obj_code.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -61,6 +61,7 @@ GBLREF int4 sym_table_size;
GBLREF int4 linkage_size;
GBLREF uint4 lnkrel_cnt; /* number of entries in linkage Psect to relocate */
GBLREF spdesc stringpool;
+GBLREF char object_file_name[];
#define PTEXT_OFFSET SIZEOF(rhdtyp)
@@ -113,7 +114,9 @@ void obj_code (uint4 src_lines, void *checksum_ctx)
rhdtyp rhead;
mline *mlx, *mly;
var_tabent *vptr;
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
assert(!run_time);
obj_init();
/* Define the routine name global symbol */
@@ -209,6 +212,8 @@ void obj_code (uint4 src_lines, void *checksum_ctx)
rhead.temp_mvals = sa_temps[TVAL_REF];
rhead.temp_size = sa_temps_offset[TCAD_REF];
rhead.compiler_qlf = cmd_qlf.qlf;
+ if (cmd_qlf.qlf & CQ_EMBED_SOURCE)
+ rhead.routine_source_offset = TREF(routine_source_offset);
/* Start the creation of the output object */
create_object_file(&rhead);
cg_phase = CGP_MACHINE;
@@ -293,6 +298,8 @@ void obj_code (uint4 src_lines, void *checksum_ctx)
emit_immed(PADCHARS, object_pad_size);
}
close_object_file();
+ /* Ready to make object visible. Rename from tmp name to real routine name */
+ rename_tmp_object_file(object_file_name);
}
/* Routine called to process a given label. Cheezy 2nd parm is due to general purpose
diff --git a/sr_unix/ojchildioclean.c b/sr_unix/ojchildioclean.c
index 5ac10fc..24a28f3 100644
--- a/sr_unix/ojchildioclean.c
+++ b/sr_unix/ojchildioclean.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -28,6 +28,9 @@
#ifdef GTM_CRYPT
#include "gtmcrypt.h"
#endif
+#include <rtnhdr.h>
+#include "relinkctl.h"
+#include "zhist.h"
GBLREF int mutex_sock_fd;
@@ -39,10 +42,12 @@ void ojchildioclean(void)
sgmnt_data_ptr_t csd;
gd_region *r_top, *r_local;
gd_addr *addr_ptr;
+ open_relinkctl_sgm *linkctl;
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
/* Close any encryption related fds that the plug-in might have opened */
GTMCRYPT_ONLY(GTMCRYPT_CLOSE;)
-
/* Run through the list of databases to simply close them out (still open by parent) */
for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr))
{
@@ -70,4 +75,9 @@ void ojchildioclean(void)
if (FD_INVALID != mutex_sock_fd)
CLOSEFILE_RESET(mutex_sock_fd, rc); /* resets "mutex_sock_fd" to FD_INVALID */
#endif
+ /* Since we are removing artifacts from the originating process (which still has these files open), there is
+ * no need to decrement the counts (they will increase if this process links the same files). The FALSE
+ * argument prevents the count from being modified in this cleanup.
+ */
+ USHBIN_ONLY(relinkctl_rundown(FALSE));
}
diff --git a/sr_unix/ojstartchild.c b/sr_unix/ojstartchild.c
index 17f368c..c3e2d09 100644
--- a/sr_unix/ojstartchild.c
+++ b/sr_unix/ojstartchild.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -69,8 +69,10 @@ GBLREF int sys_nerr;
#pragma pointer_size (long)
#endif
-GBLREF char **environ;
-GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF char **environ;
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
+LITREF gtmImageName gtmImageNames[];
#ifdef __osf__
#pragma pointer_size (restore)
@@ -101,15 +103,15 @@ GBLREF char gtm_dist[GTM_PATH_MAX];
} \
}
-#define FORK_RETRY(PID) \
-{ \
- FORK(PID); /* BYPASSOK: we die after creating a child, no FORK_CLEAN needed */ \
- while (-1 == PID) \
- { \
- assertpro(EAGAIN == errno || ENOMEM == errno); \
- usleep(50000); \
- FORK(PID); /* BYPASSOK: we die after creating a child, no FORK_CLEAN needed */ \
- } \
+#define FORK_RETRY(PID) \
+{ \
+ FORK(PID); \
+ while (-1 == PID) \
+ { \
+ assertpro(EAGAIN == errno || ENOMEM == errno); \
+ usleep(50000); \
+ FORK(PID); \
+ } \
}
#define SETUP_OP_FAIL() \
@@ -130,6 +132,7 @@ GBLREF char gtm_dist[GTM_PATH_MAX];
_exit(joberr); \
}
+error_def(ERR_GTMDISTUNVERIF);
error_def(ERR_JOBFAIL);
error_def(ERR_JOBPARTOOLONG);
error_def(ERR_LOGTOOLONG);
@@ -274,6 +277,13 @@ int ojstartchild (job_params_type *jparms, int argcnt, boolean_t *non_exit_retur
#ifdef __osf__
#pragma pointer_size (restore)
#endif
+ /* Do the fork and exec but BEFORE that do a FFLUSH(NULL) to make sure any fclose (done in io_rundown
+ * in the child process) does not affect file offsets in this (parent) process' file descriptors
+ */
+ if (!gtm_dist_ok_to_use)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, STRLEN(gtm_dist), gtm_dist,
+ gtmImageNames[image_type].imageNameLen, gtmImageNames[image_type].imageName);
+ FFLUSH(NULL);
FORK_RETRY(child_pid);
if (child_pid == 0)
{
diff --git a/sr_unix/op_fnfgncal.c b/sr_unix/op_fnfgncal.c
index a2a5492..ea51700 100644
--- a/sr_unix/op_fnfgncal.c
+++ b/sr_unix/op_fnfgncal.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -77,7 +77,7 @@
* lookup package
* Return package_handle if success, NULL otherwise.
*
- * void * fgn_getpak(char *package_name)
+ * void * fgn_getpak(char *package_name, int error_severity)
* {
* lookup package
* If not found, return NULL;
diff --git a/sr_unix/op_fnzpeek.c b/sr_unix/op_fnzpeek.c
index 62b0ebe..73c81db 100644
--- a/sr_unix/op_fnzpeek.c
+++ b/sr_unix/op_fnzpeek.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -41,8 +41,6 @@ error_def(ERR_MAXSTRLEN);
error_def(ERR_ZPEEKNORPLINFO);
#define FMTHEXDGT(spfree, digit) *spfree++ = digit + ((digit <= 9) ? '0' : ('A' - 0x0A))
-#define ZPEEKDEFFMT "C"
-#define ZPEEKDEFFMT_LEN (SIZEOF(ZPEEKDEFFMT) - 1)
#define ARGUMENT_MAX_LEN MAX_MIDENT_LEN
/* Codes for peek operation mnemonics */
@@ -68,9 +66,10 @@ GBLREF boolean_t pool_init;
GBLREF boolean_t jnlpool_init_needed;
GBLREF jnlpool_addrs jnlpool;
GBLREF recvpool_addrs recvpool;
-DEBUG_ONLY(GBLREF boolean_t ok_to_UNWIND_in_exit_handling;)
+#ifdef DEBUG
+GBLREF int process_exiting;
+#endif
-LITDEF mval literal_zpeekdeffmt = DEFINE_MVAL_LITERAL(MV_STR, 0, 0, ZPEEKDEFFMT_LEN, (char *)ZPEEKDEFFMT, 0, 0);
LITREF unsigned char lower_to_upper_table[];
STATICFNDCL void op_fnzpeek_signal_handler(int sig, siginfo_t *info, void *context);
@@ -153,7 +152,7 @@ void op_fnzpeek_signal_handler(int sig, siginfo_t *info, void *context)
{ /* Needs new block since START_CH declares a new var used in UNWIND() */
int arg = 0; /* Needed for START_CH macro if debugging enabled */
START_CH(TRUE);
- DEBUG_ONLY(ok_to_UNWIND_in_exit_handling = TRUE);
+ assert(!process_exiting);
UNWIND(NULL, NULL);
}
}
@@ -422,10 +421,7 @@ void op_fnzpeek(mval *structid, int offset, int len, mval *format, mval *ret)
/* Initialize */
fmtcode = 'C'; /* If arg is NULL string (noundef default), provide default */
MV_FORCE_STR(structid);
- if (MV_DEFINED(format))
- {
- MV_FORCE_STR(format);
- } else format = (mval *)&literal_zpeekdeffmt; /* Cast to avoid compiler warning about dropping readonly type attributes */
+ MV_FORCE_STR(format);
/* Parse and lookup the first arg's mnemonic and arg (if supplied) */
for (nptr = mnemonic, cptr = (unsigned char *)structid->str.addr, cptrend = cptr + structid->str.len;
cptr < cptrend; ++cptr)
diff --git a/sr_unix/op_fnzsearch.c b/sr_unix/op_fnzsearch.c
index c99d4ca..6f2332f 100644
--- a/sr_unix/op_fnzsearch.c
+++ b/sr_unix/op_fnzsearch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -37,6 +37,7 @@
#include "gdsbt.h"
#include "gdsfhead.h"
#include "alias.h"
+#include "op_fnzsearch.h"
GBLREF symval *curr_symval;
GBLREF boolean_t gtm_utf8_mode;
@@ -44,11 +45,10 @@ GBLREF spdesc stringpool;
LITREF mval literal_null;
-STATICFNDCL CONDITION_HANDLER(fnzsrch_ch);
-STATICFNDCL CONDITION_HANDLER(dir_ch);
-STATICFNDCL int pop_top(lv_val *src, mval *res);
-
-void dir_srch(parse_blk *pfil);
+STATICFNDCL CONDITION_HANDLER(fnzsrch_ch);
+STATICFNDCL CONDITION_HANDLER(dir_ch);
+STATICFNDCL int pop_top(lv_val *src, mval *res);
+STATICFNDCL void dir_srch(parse_blk *pfil);
error_def(ERR_ASSERT);
error_def(ERR_GTMASSERT);
@@ -57,8 +57,9 @@ error_def(ERR_GTMCHECK);
error_def(ERR_INVSTRLEN);
error_def(ERR_MEMORY);
error_def(ERR_STACKOFLOW);
+error_def(ERR_ZSRCHSTRMCT);
-int op_fnzsearch(mval *file, mint indx, mval *ret)
+int op_fnzsearch(mval *file, mint indx, mint mfunc, mval *ret)
{
struct stat statbuf;
int stat_res;
@@ -71,6 +72,8 @@ int op_fnzsearch(mval *file, mint indx, mval *ret)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
+ if (mfunc && ((MAX_STRM_CT < indx) || ( 0 > indx))) /* Allow out-of-range stream if internal call */
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZSRCHSTRMCT);
ESTABLISH_RET(fnzsrch_ch, -1);
TREF(fnzsearch_nullsubs_sav) = TREF(lv_null_subs);
TREF(lv_null_subs) = LVNULLSUBS_OK; /* $ZSearch processing depends on this */
@@ -162,7 +165,7 @@ int op_fnzsearch(mval *file, mint indx, mval *ret)
return pret.p.pint;
}
-void dir_srch(parse_blk *pfil)
+STATICFNDEF void dir_srch(parse_blk *pfil)
{
struct stat statbuf;
int stat_res;
diff --git a/sr_unix/op_fnzsyslog.c b/sr_unix/op_fnzsyslog.c
new file mode 100644
index 0000000..5992068
--- /dev/null
+++ b/sr_unix/op_fnzsyslog.c
@@ -0,0 +1,47 @@
+ /****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include "gtm_string.h"
+
+#include "min_max.h"
+#include "op.h"
+#include "util.h"
+
+LITREF mval literal_one;
+
+void op_fnzsyslog(mval* src, mval* dst)
+{
+ char rebuff[OUT_BUFF_SIZE];
+ int len;
+ char *save_util_outptr;
+ va_list save_last_va_list_ptr;
+ boolean_t util_copy_saved = FALSE;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ MV_FORCE_STR(src);
+ len = MIN(src->str.len, OUT_BUFF_SIZE - 1);
+ if (0 < len)
+ {
+ if ((NULL != TREF(util_outptr)) && (TREF(util_outptr) != TREF(util_outbuff_ptr)))
+ {
+ SAVE_UTIL_OUT_BUFFER(save_util_outptr, save_last_va_list_ptr, util_copy_saved);
+ }
+ memcpy(rebuff, src->str.addr, len); /* Rebuffer to add null terminator */
+ rebuff[len] = '\0'; /* Add null terminator */
+ util_out_print(NULL, RESET);
+ util_out_print(rebuff, OPER);
+ RESTORE_UTIL_OUT_BUFFER(save_util_outptr, save_last_va_list_ptr, util_copy_saved);
+ }
+ memcpy(dst, &literal_one, SIZEOF(mval));
+}
diff --git a/sr_unix/op_job.c b/sr_unix/op_job.c
index 0b3d3e6..337152e 100644
--- a/sr_unix/op_job.c
+++ b/sr_unix/op_job.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -91,7 +91,7 @@ int op_job(int4 argcnt, ...)
{
va_list var;
int4 i;
- mval *label, *inp;
+ mval *label;
int4 offset;
mval *routine, *param_buf;
int4 timeout; /* timeout in seconds */
@@ -114,6 +114,8 @@ int op_job(int4 argcnt, ...)
int4 index;
DCL_THREADGBL_ACCESS;
+ LITREF mval skiparg;
+
SETUP_THREADGBL_ACCESS;
VAR_START(var, argcnt);
assert(argcnt >= 5);
@@ -152,8 +154,6 @@ int op_job(int4 argcnt, ...)
va_end(var);
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_JOBFAIL, 0, ERR_NULLENTRYREF, 0);
}
- /* Clear the buffers */
- flush_pio();
/* Start the timer */
ojtimeout = FALSE;
if (timeout < 0)
@@ -177,8 +177,9 @@ int op_job(int4 argcnt, ...)
i = argcnt;
for(;;)
{
- inp = va_arg(var, mval *);
- jp->parm = inp;
+ jp->parm = va_arg(var, mval *);
+ if (!M_ARG_SKIPPED(jp->parm))
+ MV_FORCE_STR(jp->parm);
if (0 == --i)
break;
jp->next = jp + 1;
diff --git a/sr_port/m_break.c b/sr_unix/op_lab_ext.c
similarity index 50%
copy from sr_port/m_break.c
copy to sr_unix/op_lab_ext.c
index c59bf66..6fa4396 100644
--- a/sr_port/m_break.c
+++ b/sr_unix/op_lab_ext.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Inforformation Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -10,23 +10,23 @@
****************************************************************/
#include "mdef.h"
-#include "compiler.h"
-#include "opcode.h"
-#include "toktyp.h"
-#include "cmd.h"
-int m_break(void)
+#include <rtnhdr.h>
+
+#ifdef USHBIN_SUPPORTED /* entire file */
+/* Routine to provide the content of the thread-local variable "lab_lnr" as a return value to
+ * generated code.
+ *
+ * Parameters: none
+ *
+ * Return value:
+ * - Address of line-number table entry corresponding to the entryref's label
+ */
+void *op_lab_ext(void)
{
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- if ((TK_SPACE != TREF(window_token)) && (TK_EOL != TREF(window_token)))
- if (!m_xecute())
- return FALSE;
- newtriple(OC_BREAK);
- if (TREF(for_stack_ptr) == TADR(for_stack))
- start_fetches (OC_FETCH);
- else
- start_for_fetches ();
- return TRUE;
+ return TREF(lab_lnr);
}
+#endif /* USHBIN_SUPPORTED over entire file */
diff --git a/sr_unix/op_rhd_ext.c b/sr_unix/op_rhd_ext.c
new file mode 100644
index 0000000..13673ae
--- /dev/null
+++ b/sr_unix/op_rhd_ext.c
@@ -0,0 +1,92 @@
+/****************************************************************
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#ifdef USHBIN_SUPPORTED /* entire file */
+#include "gtm_string.h"
+
+#include <rtnhdr.h>
+#include "op.h"
+#include "relinkctl.h"
+#include "zhist.h"
+#include "min_max.h"
+
+/* Rebuffering macro for routine and label name for use when needed. Note we don't even do the
+ * MV_FORCE_STR() on the given mval until we know we are going to use it.
+ */
+#define REBUFFER_MIDENT(MVAL, NEWMVAL, BUFFER) \
+{ \
+ MV_FORCE_STR(MVAL); \
+ *(NEWMVAL) = *(MVAL); \
+ (NEWMVAL)->str.len = MIN(MAX_MIDENT_LEN, (NEWMVAL)->str.len); \
+ memcpy((BUFFER), (NEWMVAL)->str.addr, (NEWMVAL)->str.len); \
+ (NEWMVAL)->str.addr = (char *)&(BUFFER); \
+}
+
+/* Routine called from both generated code and internally to check if a given routine/label need to be auto(re)linked and
+ * do so if needbe.
+ *
+ * Parameters:
+ * - rtnname - address of mval pointing to text of routine name.
+ * - lblname - address of mval pointing to text of label name.
+ * - rhd - address of routine header (if filled in in linkage table or NULL if not).
+ * - lnr - address of linenumber table entry (offset) associated with text label or NULL if not yet linked.
+ *
+ * Return value:
+ * - routine header address of current routine.
+ */
+rhdtyp *op_rhd_ext(mval *rtname, mval *lbname, rhdtyp *rhd, void *lnr)
+{
+ lnr_tabent **lnrptr;
+ char rtnname_buff[MAX_MIDENT_LEN], lblname_buff[MAX_MIDENT_LEN];
+ mval rtnname, lblname;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ /* The are two potential future updates here:
+ * 1. Desire to remove the two additional opcodes and revert back to the single call opcode (op_call, op_extexfun, etc).
+ * This would have positive performance enhancements through less generated code and shorter call path if doable.
+ * 2. Intention is to change the syntax of ZRUPDATE such that routines can be specified in groups surrounded by
+ * parentheses (e.g. ZRUPDATE (a.o,b.o,c.o)) which would make all 3 routines available simultaneously instead of
+ * serially. This will likely require some sort of locking protocols but is not yet defined.
+ */
+ if (NULL == rhd)
+ { /* Routine is not yet linked - perform auto-ZLINK */
+ REBUFFER_MIDENT(rtname, &rtnname, rtnname_buff);
+ REBUFFER_MIDENT(lbname, &lblname, lblname_buff);
+ rhd = op_rhdaddr1(&rtnname);
+ op_labaddr(rhd, &lblname, 0); /* Offset != 0 would not go through op_rhd_ext */
+ TREF(lab_lnr) = &((TREF(lab_proxy)).lnr_adr);
+ /* lab_proxy now set by op_labaddr; ready for op_lab_ext next */
+ return rhd;
+ }
+ /* Routine is already linked, but we need to check if a new version is available. This involves traversing the
+ * "validation linked list", looking for changes in different $zro entries. But we also need to base our checks
+ * on the most recent version of the routine loaded.
+ */
+ rhd = rhd->current_rhead_adr;
+ if ((NULL != rhd->zhist) && need_relink(rhd, (zro_hist *)rhd->zhist))
+ {
+ REBUFFER_MIDENT(rtname, &rtnname, rtnname_buff);
+ REBUFFER_MIDENT(lbname, &lblname, lblname_buff);
+ op_zlink(&rtnname, NULL);
+ rhd = rhd->current_rhead_adr; /* Pickup routine header of new version to avoid lookup */
+ assert((NULL == rhd->zhist) || (((zro_hist *)(rhd->zhist))->zroutines_cycle == TREF(set_zroutines_cycle)));
+ op_labaddr(rhd, &lblname, 0);
+ TREF(lab_lnr) = &((TREF(lab_proxy)).lnr_adr);
+ return rhd;
+ }
+ /* Linked routine is already the latest */
+ TREF(lab_lnr) = lnr;
+ return rhd;
+}
+#endif /* USHBIN_SUPPORTED */
diff --git a/sr_unix/op_zedit.c b/sr_unix/op_zedit.c
index 9ef7204..c995e3f 100644
--- a/sr_unix/op_zedit.c
+++ b/sr_unix/op_zedit.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -158,7 +158,7 @@ void op_zedit(mval *v, mval *p)
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
sigaction(SIGINT, &act, &intr);
- FORK(childid); /* BYPASSOK: we exec immediately, no FORK_CLEAN needed */
+ FORK(childid);
if (childid)
{
waitid = (int)childid;
diff --git a/sr_unix/op_zlink.c b/sr_unix/op_zlink.c
index 1fbf0e9..ebc5c32 100644
--- a/sr_unix/op_zlink.c
+++ b/sr_unix/op_zlink.c
@@ -1,5 +1,6 @@
-/**************************************************************** * *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+/****************************************************************
+ * *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,6 +34,17 @@
#define OBJ 2
#define NOTYPE 3
+/* On shared platforms, skip parameter should be FALSE to indicate an auto-ZLINK so that
+ * zro_search looks into shared libraries. On non-shared platforms, it should be
+ * TRUE to instruct zro_search to always skip shared libraries
+ */
+#define SKIP_SHLIBS TRUE
+#ifdef USHBIN_SUPPORTED
+#define PROBE_SHLIBS (!SKIP_SHLIBS) /* i.e., don't skip (skip = FALSE) */
+#else
+#define PROBE_SHLIBS SKIP_SHLIBS
+#endif
+
/* On certain platforms the st_mtime field of the stat structure got replaced by a timespec st_mtim field, which in turn has tv_sec
* and tv_nsec fields. For compatibility reasons, those platforms define an st_mtime macro which points to st_mtim.tv_sec. Whenever
* we detect such a situation, we define a nanosecond flavor of that macro to point to st_mtim.tv_nsec. On HPUX Itanium and older
@@ -47,6 +59,8 @@
# define st_nmtime st_nmtime
#endif
+#define CLOSE_OBJECT_FD(FD, STATUS) CLOSEFILE_RESET(FD, STATUS) /* resets "object_file_des" to FD_INVALID */
+
GBLREF spdesc stringpool;
GBLREF command_qualifier glb_cmd_qlf, cmd_qlf;
GBLREF mval dollar_zsource;
@@ -61,6 +75,20 @@ error_def(ERR_FILEPARSE);
error_def(ERR_TEXT);
ZOS_ONLY(error_def(ERR_BADTAG);)
+/* Routine to locate object files, or source and compile to an object file if necessary, and drive the linker to link the file
+ * into this process appropriately. Three types of linking are currently supported on UNIX platforms (excepting Linux i386 which
+ * has its own less fully-featured linker):
+ *
+ * 1. Link into process private - Executable code becomes part of the process private space.
+ * 2. Link from a shared library - M routines linked into a shared library can be linked into a process allowing much of the
+ * object file to be shared.
+ * 3. Link from a shared object - Current mechanism is to mmap() the object file and link it similar to how shared library links
+ * are done.
+ *
+ * Parameters:
+ * - v - mval containing the name/path of the object file.
+ * - quals - mval containing the ZLINK command options (see GT.M User's Guide).
+ */
void op_zlink (mval *v, mval *quals)
{
int status, qlf, tslash;
@@ -80,26 +108,26 @@ void op_zlink (mval *v, mval *quals)
SETUP_THREADGBL_ACCESS;
MV_FORCE_STR(v);
if (!v->str.len || (MAX_FBUFF < v->str.len))
- rts_error_csa(NULL, VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
object_file_des = FD_INVALID;
- srcdir = objdir = (zro_ent *) 0;
+ srcdir = objdir = NULL;
expdir = FALSE;
if (quals)
- { /* explicit ZLINK */
+ { /* Explicit ZLINK */
memset(&pblk, 0, SIZEOF(pblk));
pblk.buff_size = MAX_FBUFF;
pblk.buffer = inputf;
pblk.fop = F_SYNTAXO;
status = parse_file(&v->str, &pblk);
if (!(status & 1))
- rts_error_csa(NULL, VARLSTCNT(5) ERR_FILEPARSE, 2, v->str.len, v->str.addr, status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, v->str.len, v->str.addr, status);
if (pblk.fnb & F_WILD)
- rts_error_csa(NULL, VARLSTCNT(8) ERR_ZLINKFILE, 2, v->str.len, v->str.addr,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZLINKFILE, 2, v->str.len, v->str.addr,
ERR_WILDCARD, 2, v->str.len, v->str.addr);
file.addr = pblk.buffer;
file.len = pblk.b_esl;
type = NOTYPE;
- expdir = 0 != (pblk.fnb & F_HAS_DIR);
+ expdir = (0 != (pblk.fnb & F_HAS_DIR));
if (pblk.b_ext)
{
file.len -= pblk.b_ext;
@@ -139,9 +167,9 @@ void op_zlink (mval *v, mval *quals)
assert (objnamelen + SIZEOF(DOTOBJ) <= MAX_FBUFF + 1);
} else
{
- if (file.len + SIZEOF(DOTM) > SIZEOF(srcnamebuf) ||
- file.len + SIZEOF(DOTOBJ) > SIZEOF(objnamebuf))
- rts_error_csa(NULL, VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
+ if ((file.len + SIZEOF(DOTM) > SIZEOF(srcnamebuf)) ||
+ (file.len + SIZEOF(DOTOBJ) > SIZEOF(objnamebuf)))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
memmove(srcnamebuf, file.addr, file.len);
memcpy(&srcnamebuf[file.len], DOTM, SIZEOF(DOTM));
srcnamelen = file.len + SIZEOF(DOTM) - 1;
@@ -159,30 +187,30 @@ void op_zlink (mval *v, mval *quals)
objstr.len = objnamelen;
if (OBJ == type)
{
- zro_search(&objstr, &objdir, 0, 0, TRUE);
+ zro_search(&objstr, &objdir, NULL, NULL, SKIP_SHLIBS);
if (!objdir)
- rts_error_csa(NULL, VARLSTCNT(8) ERR_ZLINKFILE, 2, dollar_zsource.str.len,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZLINKFILE, 2, dollar_zsource.str.len,
dollar_zsource.str.addr, ERR_FILENOTFND,2, dollar_zsource.str.len,
dollar_zsource.str.addr);
} else if (SRC == type)
{
- zro_search(&objstr, &objdir, &srcstr, &srcdir, TRUE);
+ zro_search(&objstr, &objdir, &srcstr, &srcdir, SKIP_SHLIBS);
if (!srcdir)
- rts_error_csa(NULL, VARLSTCNT(8) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf,
ERR_FILENOTFND, 2, srcnamelen, srcnamebuf);
} else
{
- zro_search(&objstr, &objdir, &srcstr, &srcdir, NON_USHBIN_ONLY(TRUE) USHBIN_ONLY(FALSE));
+ zro_search(&objstr, &objdir, &srcstr, &srcdir, PROBE_SHLIBS);
if (!objdir && !srcdir)
- rts_error_csa(NULL, VARLSTCNT(8) ERR_ZLINKFILE, 2, dollar_zsource.str.len,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZLINKFILE, 2, dollar_zsource.str.len,
dollar_zsource.str.addr, ERR_FILENOTFND,2, dollar_zsource.str.len,
dollar_zsource.str.addr);
}
}
} else
- { /* auto-ZLINK */
+ { /* auto-ZLINK */
type = NOTYPE;
- memcpy(srcnamebuf,v->str.addr,v->str.len);
+ memcpy(srcnamebuf, v->str.addr, v->str.len);
memcpy(&srcnamebuf[v->str.len], DOTM, SIZEOF(DOTM));
srcnamelen = v->str.len + SIZEOF(DOTM) - 1;
if ('%' == srcnamebuf[0])
@@ -194,13 +222,9 @@ void op_zlink (mval *v, mval *quals)
srcstr.len = srcnamelen;
objstr.addr = objnamebuf;
objstr.len = objnamelen;
- /* On shared platforms, skip parameter should be FALSE to indicate an auto-ZLINK so that
- * zro_search looks into shared libraries. On non-shared platforms, it should be
- * TRUE to instruct zro_search to always skip shared libraries
- */
- zro_search(&objstr, &objdir, &srcstr, &srcdir, NON_USHBIN_ONLY(TRUE) USHBIN_ONLY(FALSE));
+ zro_search(&objstr, &objdir, &srcstr, &srcdir, PROBE_SHLIBS);
if (!objdir && !srcdir)
- rts_error_csa(NULL, VARLSTCNT(8) ERR_ZLINKFILE, 2, v->str.len, v->str.addr,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZLINKFILE, 2, v->str.len, v->str.addr,
ERR_FILENOTFND, 2, v->str.len, v->str.addr);
qualifier.mvtype = MV_STR;
qualifier.str = TREF(dollar_zcompile);
@@ -212,7 +236,7 @@ void op_zlink (mval *v, mval *quals)
{
assert(ZRO_TYPE_OBJLIB != objdir->type);
if (objdir->str.len + objnamelen + 2 > SIZEOF(objnamebuf))
- rts_error_csa(NULL, VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
if (objdir->str.len)
{
tslash = ('/' == objdir->str.addr[objdir->str.len - 1]) ? 0 : 1;
@@ -226,17 +250,22 @@ void op_zlink (mval *v, mval *quals)
}
OPEN_OBJECT_FILE(objnamebuf, O_RDONLY, object_file_des);
if (FD_INVALID == object_file_des)
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr,
errno);
- if (USHBIN_ONLY(!incr_link(object_file_des, NULL)) NON_USHBIN_ONLY(!incr_link(object_file_des)))
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr,
- ERR_VERSION);
- CLOSEFILE_RESET(object_file_des, status); /* resets "object_file_des" to FD_INVALID */
+ if (IL_RECOMPILE == incr_link(object_file_des, NULL, objnamelen, objnamebuf))
+ {
+ CLOSE_OBJECT_FD(object_file_des, status); /* No checking for error here as the priority error
+ * right now is the version issue.
+ */
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr,
+ ERR_VERSION);
+ }
+ CLOSE_OBJECT_FD(object_file_des, status);
if (-1 == status)
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr,
errno);
- } else /* either NO type or SOURCE type */
- {
+ } else
+ { /* either NO type or SOURCE type */
cmd_qlf.object_file.str.addr = obj_file;
cmd_qlf.object_file.str.len = MAX_FBUFF;
cmd_qlf.list_file.str.addr = list_file;
@@ -247,7 +276,7 @@ void op_zlink (mval *v, mval *quals)
{
assert(ZRO_TYPE_OBJLIB != objdir->type);
if (srcdir->str.len + srcnamelen > SIZEOF(srcnamebuf) - 1)
- rts_error_csa(NULL, VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
if (srcdir->str.len)
{
tslash = ('/' == srcdir->str.addr[srcdir->str.len - 1]) ? 0 : 1;
@@ -263,14 +292,16 @@ void op_zlink (mval *v, mval *quals)
{
if (ZRO_TYPE_OBJLIB == objdir->type)
{
- NON_USHBIN_ONLY(assertpro(FALSE));
assert(objdir->shrlib);
assert(objdir->shrsym);
- USHBIN_ONLY(assertpro(incr_link(0, objdir)));
+ /* The incr_link() routine should drive errors for any issue found with linking from a shared
+ * library so IL_DONE is the only valid return code we *ever* expect back.
+ */
+ assertpro(IL_DONE == incr_link(0, objdir, objnamelen, objnamebuf));
return;
}
if (objdir->str.len + objnamelen > SIZEOF(objnamebuf) - 1)
- rts_error_csa(NULL, VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZLINKFILE, 2, v->str.len, v->str.addr);
if (objdir->str.len)
{
tslash = ('/' == objdir->str.addr[objdir->str.len - 1]) ? 0 : 1;
@@ -291,7 +322,7 @@ void op_zlink (mval *v, mval *quals)
if (ENOENT == errno)
obj_found = FALSE;
else
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
} else
obj_found = TRUE;
} else
@@ -302,7 +333,7 @@ void op_zlink (mval *v, mval *quals)
if ((ENOENT == errno) && (SRC != type))
src_found = FALSE;
else
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE,2,srcnamelen,srcnamebuf,errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE,2,srcnamelen,srcnamebuf,errno);
} else
src_found = TRUE;
if (SRC != type)
@@ -313,22 +344,22 @@ void op_zlink (mval *v, mval *quals)
{
FSTAT_FILE(object_file_des, &obj_stat, status);
if (-1 == status)
- rts_error_csa(NULL,VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
+ rts_error_csa(CSA_ARG(NULL)VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf,
+ errno);
if ((src_stat.st_mtime > obj_stat.st_mtime)
|| ((src_stat.st_mtime == obj_stat.st_mtime)
&& (src_stat.st_nmtime > obj_stat.st_nmtime)))
{
- CLOSEFILE_RESET(object_file_des, status); /* resets "object_file_des"
- * to FD_INVALID */
+ CLOSE_OBJECT_FD(object_file_des, status);
if (-1 == status)
- rts_error_csa(NULL,VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf,
- errno);
+ rts_error_csa(CSA_ARG(NULL)VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen,
+ objnamebuf, errno);
compile = TRUE;
}
} else
compile = TRUE;
} else if (!obj_found)
- rts_error_csa(NULL, VARLSTCNT(8) ERR_ZLINKFILE, 2, objnamelen, objnamebuf,
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZLINKFILE, 2, objnamelen, objnamebuf,
ERR_FILENOTFND, 2, objnamelen, objnamebuf);
}
if (compile)
@@ -344,24 +375,21 @@ void op_zlink (mval *v, mval *quals)
if (!(cmd_qlf.qlf & CQ_OBJECT) && (SRC != type))
{
cmd_qlf.qlf = glb_cmd_qlf.qlf;
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_ZLNOOBJECT);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_ZLNOOBJECT);
}
zlcompile(srcnamelen, (uchar_ptr_t)srcnamebuf);
if ((SRC == type) && !(qlf & CQ_OBJECT))
return;
}
- CONVERT_OBJECT_LOCK(object_file_des, F_RDLCK, status);
- if (-1 == status)
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
- status = USHBIN_ONLY(incr_link(object_file_des, NULL)) NON_USHBIN_ONLY(incr_link(object_file_des));
- if (!status)
+ status = incr_link(object_file_des, objdir, objnamelen, objnamebuf);
+ if (IL_RECOMPILE == status)
{ /* due only to version mismatch, so recompile */
- CLOSEFILE_RESET(object_file_des, status); /* resets "object_file_des" to FD_INVALID */
+ CLOSE_OBJECT_FD(object_file_des, status);
if (-1 == status)
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
assertpro(!compile);
if (!src_found)
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_VERSION);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_VERSION);
zl_cmd_qlf(&quals->str, &cmd_qlf);
if (!MV_DEFINED(&cmd_qlf.object_file))
{
@@ -373,16 +401,17 @@ void op_zlink (mval *v, mval *quals)
if (!(cmd_qlf.qlf & CQ_OBJECT) && (SRC != type))
{
cmd_qlf.qlf = glb_cmd_qlf.qlf;
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_ZLNOOBJECT);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_ZLNOOBJECT);
}
- CONVERT_OBJECT_LOCK(object_file_des, F_RDLCK, status);
- if (-1 == status)
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
- assertpro(! (USHBIN_ONLY(!incr_link(object_file_des, NULL))
- NON_USHBIN_ONLY(!incr_link(object_file_des))) );
+ /* We just did a fresh re-compile a few lines above so IL_DONE is the only return code we ever
+ * expect to see back. Only a race-condition created by a different version overlaying the newly
+ * created object file could conceivably cause an IL_RECOMPILE code here (incr_link handles all
+ * the other errors itself). Not at this time considered worthy of special coding.
+ */
+ assertpro(IL_DONE == incr_link(object_file_des, objdir, objnamelen, objnamebuf));
}
- CLOSEFILE_RESET(object_file_des, status); /* resets "object_file_des" to FD_INVALID */
+ CLOSE_OBJECT_FD(object_file_des, status);
if (-1 == status)
- rts_error_csa(NULL, VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, errno);
}
}
diff --git a/sr_unix/op_zmess.c b/sr_unix/op_zmess.c
index 1bd4233..bbeefc4 100644
--- a/sr_unix/op_zmess.c
+++ b/sr_unix/op_zmess.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,6 +18,8 @@
#include "op.h"
#include "mval2fao.h"
#include "gtmmsg.h"
+#include "send_msg.h"
+#include "wbox_test_init.h"
#define ZMESS_DISALLWD_LIST_SIZE 10
#define FAO_BUFFER_SPACE 2048
@@ -38,8 +40,7 @@ error_def(ERR_CTRAP);
error_def(ERR_STACKCRIT);
error_def(ERR_SPCLZMSG);
-/*
- * Returns whether an errnum is not allowed to be raised by ZMESSAGE. The errors on this list generally
+/* Returns whether an errnum is not allowed to be raised by ZMESSAGE. The errors on this list generally
* trigger additional processing by the error handler which either assumes certain context to be setup
* before the processing or does something which should not be triggered manually.
*/
@@ -48,11 +49,7 @@ STATICFNDEF boolean_t is_disallowed(unsigned int errnum)
int i; /* search iterator */
if (0 == zmess_disallowed_list[0])
- {
- /*
- * Lazy initialization of the disallowed array
- * The ERR_XXXX take value at runtime, hence individual assignments.
- */
+ { /* Lazy initialization of the disallowed array. The ERR_XXXX take value at runtime, hence individual assignments. */
i = 0;
zmess_disallowed_list[i++] = ERR_REPEATERROR;
zmess_disallowed_list[i++] = ERR_TPRETRY;
@@ -67,46 +64,71 @@ STATICFNDEF boolean_t is_disallowed(unsigned int errnum)
assert(ZMESS_DISALLWD_LIST_SIZE == i);
}
- /* linear search as the list is short */
+ /* Linear search as the list is short. */
for (i = 0; i < ZMESS_DISALLWD_LIST_SIZE; ++i)
- /* message severity doesn't matter */
- if ((zmess_disallowed_list[i] >> MSGSEVERITY) == (errnum >> MSGSEVERITY))
+ if ((zmess_disallowed_list[i] >> MSGSEVERITY) == (errnum >> MSGSEVERITY)) /* Message severity doesn't matter. */
return TRUE;
return FALSE;
}
-
void op_zmess(unsigned int cnt, ...)
{
va_list var;
const err_ctl *ectl;
const err_msg *eptr;
- UINTPTR_T fao[MAX_FAO_PARMS];
+ UINTPTR_T fao[NUM_OF_FAO_SLOTS];
char buff[FAO_BUFFER_SPACE];
unsigned int errnum, j;
int faocnt;
+ int4 tmp_severity;
VAR_START(var, cnt);
+ assert(34 == MAX_FAO_PARMS); /* Defined in fao_parm.h. */
errnum = va_arg(var, int);
cnt--;
- if (NULL != (ectl = err_check(errnum))) /* note assignment */
+ if (NULL != (ectl = err_check(errnum))) /* Note assignment. */
{
GET_MSG_INFO(errnum, ectl, eptr);
+ tmp_severity = SEVMASK(errnum);
faocnt = eptr->parm_count;
faocnt = (faocnt > MAX_FAO_PARMS ? MAX_FAO_PARMS : faocnt);
faocnt = mval2fao(eptr->msg, var, &fao[0], cnt, faocnt, buff, buff + SIZEOF(buff));
va_end(var);
if (0 <= faocnt)
- if (is_disallowed(errnum))
- rts_error(VARLSTCNT(4 + faocnt) ERR_SPCLZMSG, 0, errnum, faocnt, fao[0], fao[1], fao[2], fao[3],
- fao[4], fao[5], fao[6], fao[7], fao[8], fao[9], fao[10], fao[11]);
- else
- rts_error(VARLSTCNT(2 + faocnt) errnum, faocnt, fao[0], fao[1], fao[2], fao[3], fao[4], fao[5],
- fao[6], fao[7], fao[8], fao[9], fao[10], fao[11]);
+ {
+ if (WBTEST_ENABLED(WBTEST_INFO_HUB_SEND_ZMESS))
+ {
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(2 + faocnt) errnum, faocnt, fao[0], fao[1], fao[2], fao[3],
+ fao[4], fao[5], fao[6], fao[7], fao[8], fao[9], fao[10], fao[11], fao[12], fao[13], fao[14],
+ fao[15], fao[16], fao[17], fao[18], fao[19], fao[20], fao[21], fao[22], fao[23], fao[24],
+ fao[25], fao[26], fao[27], fao[28], fao[29], fao[30], fao[31], fao[32], fao[33]);
+ } else if (is_disallowed(errnum))
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4 + faocnt) ERR_SPCLZMSG, 0, errnum, faocnt, fao[0], fao[1],
+ fao[2], fao[3], fao[4], fao[5], fao[6], fao[7], fao[8], fao[9], fao[10], fao[11], fao[12],
+ fao[13], fao[14], fao[15], fao[16], fao[17], fao[18], fao[19], fao[20], fao[21], fao[22],
+ fao[23], fao[24], fao[25], fao[26], fao[27], fao[28], fao[29], fao[30], fao[31], fao[32],
+ fao[33]);
+ } else if ((INFO == tmp_severity) || (SUCCESS == tmp_severity))
+ {
+ gtm_putmsg_noflush_csa(CSA_ARG(NULL) VARLSTCNT(2 + faocnt) errnum, faocnt, fao[0], fao[1], fao[2],
+ fao[3],fao[4], fao[5], fao[6], fao[7], fao[8], fao[9], fao[10], fao[11], fao[12], fao[13],
+ fao[14], fao[15], fao[16], fao[17], fao[18], fao[19], fao[20], fao[21], fao[22], fao[23],
+ fao[24], fao[25], fao[26], fao[27], fao[28], fao[29], fao[30], fao[31], fao[32], fao[33]);
+ PRN_ERROR;
+ } else
+ {
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(2 + faocnt) errnum, faocnt, fao[0], fao[1], fao[2], fao[3],
+ fao[4], fao[5], fao[6], fao[7], fao[8], fao[9], fao[10], fao[11], fao[12], fao[13], fao[14],
+ fao[15], fao[16], fao[17], fao[18], fao[19], fao[20], fao[21], fao[22], fao[23], fao[24],
+ fao[25], fao[26], fao[27], fao[28], fao[29], fao[30], fao[31], fao[32], fao[33]);
+ }
+
+ }
} else
{
va_end(var);
- rts_error(VARLSTCNT(1) errnum);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) errnum);
}
}
diff --git a/sr_unix/op_zrupdate.c b/sr_unix/op_zrupdate.c
new file mode 100644
index 0000000..e478dac
--- /dev/null
+++ b/sr_unix/op_zrupdate.c
@@ -0,0 +1,161 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include "gtm_limits.h"
+#include "gtm_stdio.h"
+#include "gtm_string.h"
+#include "gtm_stat.h"
+#include "gtm_stdlib.h"
+
+#include "io.h"
+#include "iosp.h"
+#include <rtnhdr.h>
+#include "relinkctl.h"
+#include "zhist.h"
+#include "parse_file.h"
+#include "eintr_wrappers.h"
+#include "error.h"
+#include "min_max.h"
+#include "op.h"
+#include "op_fnzsearch.h"
+
+#define OBJEXT 'o'
+#define WILDCARD '*'
+
+
+#ifndef USHBIN_SUPPORTED
+/* Stub routine for unsupported platforms */
+void op_zrupdate(int argcnt, ...)
+{
+ return;
+}
+#else
+/************************************************************/
+
+LITREF mval literal_null;
+
+error_def(ERR_FILEPARSE);
+error_def(ERR_PARNORMAL);
+error_def(ERR_TEXT);
+
+/*
+ * TODO: Add description of syntax/operation
+ */
+
+void op_zrupdate(int argcnt, ...)
+{
+ mval *objfilespec;
+ va_list var;
+ mval objpath;
+ char tranbuf[MAX_FBUFF + 1], *chptr;
+ open_relinkctl_sgm *linkctl;
+ relinkrec_loc_t rec;
+ plength plen;
+ int status, fextlen;
+ parse_blk pblk;
+ struct stat outbuf;
+ int stat_res;
+ boolean_t seenfext, seenwildcard;
+ mstr objdir, rtnname;
+
+ /* Currently only expecting one value per invocation right now. That will change in phase 2 hence the stdarg setup */
+ va_start(var, argcnt);
+ assert(1 == argcnt);
+ objfilespec = va_arg(var, mval *);
+ va_end(var);
+ MV_FORCE_STR(objfilespec);
+ /* First some pre-processing to determine if an explicit file type was specified. If so, it must be ".o" for this
+ * phase of implementation. Later phases may allow ".m" to be specified but not initially. Use parse_file() to
+ * parse everything out and isolate any extention.
+ */
+ memset(&pblk, 0, SIZEOF(pblk));
+ pblk.buffer = tranbuf;
+ pblk.buff_size = (unsigned char)(MAX_FBUFF);
+ pblk.fnb = 0;
+ status = parse_file(&objfilespec->str, &pblk);
+ if (ERR_PARNORMAL != status)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, objfilespec->str.len, objfilespec->str.addr, status);
+ if (0 != pblk.b_ext)
+ { /* If a file extension was specified - get the extension sans any potential wildcard character */
+ seenfext = seenwildcard = FALSE;
+ for (chptr = pblk.l_ext + 1, fextlen = pblk.b_ext - 1; 0 < fextlen; chptr++, fextlen--)
+ { /* Check each character in the extension except first which is the dot if ext exists at all */
+ if (WILDCARD != *chptr)
+ { /* We see a char that isn't a wildcard character. If we've already seen our "o" file extension,
+ * this char makes our requirement filetype impossible so raise an error.
+ * TODO - more appropriate error
+ */
+ if (seenfext || (OBJEXT != *chptr))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_FILEPARSE, 2, objfilespec->str.len,
+ objfilespec->str.addr);
+ seenfext = TRUE; /* No return from rts_error() above so this is our object file type */
+ } else
+ seenwildcard = TRUE;
+ }
+ }
+ /* When specifying a non-wildcarded object file, it is possible for the file to have been removed, in which case we still
+ * need to update its relinkctl entry (if exists) to notify other processes about the object's deletion.
+ * TODO: should this see if given object exists in relinkctl file? If not, should it error or just ignore?
+ */
+ if (!seenwildcard & seenfext)
+ {
+ objdir.addr = pblk.l_dir;
+ objdir.len = pblk.b_dir;
+ linkctl = relinkctl_attach(&objdir); /* Create/attach/open relinkctl file */
+ if (NULL == linkctl)
+ return; /* Path doesn't exist - ignore */
+ rtnname.len = MIN(MAX_MIDENT_LEN, pblk.b_name); /* Avoid overflow */
+ rtnname.addr = pblk.l_name;
+ rec = relinkctl_insert_record(linkctl, &rtnname);
+ RELINKCTL_CYCLE_INCR(linkctl, rec); /* Increment cycle indicating change to world */
+ return;
+ }
+ /* If we have a wildcarded request or one without the object filetype, reprocess the string with $ZSEARCH using our
+ * defined stream to resolve wildcards. Then loop through processing each file returned. In this loop, we just ignore
+ * any file that doesn't have a ".o" extension.
+ */
+ op_fnzsearch((mval *)&literal_null, STRM_ZRUPDATE, 0, &objpath); /* Clear any existing cache */
+ while(TRUE)
+ {
+ plen.p.pint = op_fnzsearch(objfilespec, STRM_ZRUPDATE, 0, &objpath);
+ if (0 == objpath.str.len)
+ /* End of file list */
+ break;
+ /* The extension contains the extension-start character ('.') so we are looking for the extension '.o' hence
+ * the length must be 2 and the 2nd char must be OBJEXT.
+ */
+ if ((2 == plen.p.pblk.b_ext) && (OBJEXT == *(objpath.str.addr + plen.p.pblk.b_dir + plen.p.pblk.b_name + 1)))
+ { /* This is (probably) an object file. Double check file is a file and not a directory */
+ memcpy(tranbuf, objpath.str.addr, objpath.str.len); /* Need null terminated version for STAT */
+ tranbuf[objpath.str.len] = '\0';
+ STAT_FILE(tranbuf, &outbuf, stat_res);
+ /* If either something happened to the file since op_fnzsearch() saw it or the file is not a file, then
+ * ignore it.
+ */
+ if ((-1 == stat_res) || !S_ISREG(outbuf.st_mode))
+ continue;
+ objdir.addr = objpath.str.addr;
+ objdir.len = plen.p.pblk.b_dir;
+ linkctl = relinkctl_attach(&objdir); /* Create/attach/open relinkctl file */
+ if (NULL == linkctl)
+ continue; /* Path disappeared - ignore */
+ rtnname.len = MIN(MAX_MIDENT_LEN, plen.p.pblk.b_name); /* Avoid overflow */
+ rtnname.addr = objpath.str.addr + plen.p.pblk.b_dir;
+ rec = relinkctl_insert_record(linkctl, &rtnname);
+ RELINKCTL_CYCLE_INCR(linkctl, rec); /* Increment cycle indicating change to world */
+ }
+ }
+}
+#endif /* USHBIN_SUPPORTED */
diff --git a/sr_unix/open_object_file.c b/sr_unix/open_object_file.c
new file mode 100644
index 0000000..6e35c42
--- /dev/null
+++ b/sr_unix/open_object_file.c
@@ -0,0 +1,111 @@
+/****************************************************************
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include <sys/types.h>
+#include "gtm_stat.h"
+#include "gtm_stdlib.h"
+#include "gtm_string.h"
+#include "gtm_limits.h"
+
+#include "cmd_qlf.h"
+#include "gtmio.h"
+#include "parse_file.h"
+
+GBLDEF char tmp_object_file_name[MAX_FBUFF + 1];
+
+GBLREF command_qualifier cmd_qlf;
+GBLREF char object_file_name[];
+GBLREF short object_name_len;
+GBLREF mident module_name;
+
+error_def(ERR_FILEPARSE);
+error_def(ERR_OBJFILERR);
+
+/* Open object file - TODO: make into macro instead of routine */
+int open_object_file(const char *fname, int fflag)
+{
+ int fdesc;
+
+ OPENFILE3(fname, fflag, 0666, fdesc);
+ return fdesc;
+}
+
+/* TODO - Move these routines to obj_file.c */
+/* Routine to create a temporary object file. This file is created in the directory it is supposed to reside in but is created
+ * with a temporary name. When complete, it is renamed to what it was meant to be replacing the previous version.
+ *
+ * Parameters:
+ *
+ * object_fname - Character array of the object path/name.
+ * object_fname_len - Length of that array in bytes.
+ *
+ * Output:
+ * File descriptor for the open object file.
+ */
+int mk_tmp_object_file(const char *object_fname, int object_fname_len)
+{
+ int fdesc, status;
+ int umask_creat, umask_orig;
+
+ /* TODO Verify addition of XXXXXX doesn't exceed dimensions of array */
+ memcpy(tmp_object_file_name, object_fname, object_fname_len);
+ memcpy(&tmp_object_file_name[object_fname_len], "XXXXXX", 7); /* Includes null terminator */
+ fdesc = mkstemp(tmp_object_file_name);
+ if (FD_INVALID == fdesc)
+ {
+ printf("tmp_object_file_name: %s\n", tmp_object_file_name);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_OBJFILERR, 2, object_fname_len, object_fname, errno);
+ }
+ umask_orig = umask(000); /* Determine umask (destructive) */
+ (void)umask(umask_orig); /* Reset umask */
+ umask_creat = 0666 & ~umask_orig;
+ /* TODO: set protections appropriately (if this isn't it) */
+ FCHMOD(fdesc, umask_creat);
+ return fdesc;
+}
+
+void rename_tmp_object_file(const char *object_fname)
+{
+ rename(tmp_object_file_name, object_fname); /* TODO - Handle error (SEE) and make into macro instead of routine */
+}
+
+/*
+ * Inputs: cmd_qlf.object_file, module_name
+ * Outputs: object_file_name, object_name_len
+ */
+void init_object_file_name(void)
+{
+ int status, rout_len;
+ char obj_name[SIZEOF(mident_fixed) + 5];
+ mstr fstr;
+ parse_blk pblk;
+
+ memset(&pblk, 0, SIZEOF(pblk));
+ pblk.buffer = object_file_name;
+ pblk.buff_size = MAX_FBUFF;
+
+ /* Create the object file */
+ fstr.len = (MV_DEFINED(&cmd_qlf.object_file) ? cmd_qlf.object_file.str.len : 0);
+ fstr.addr = cmd_qlf.object_file.str.addr;
+ rout_len = (int)module_name.len;
+ memcpy(&obj_name[0], module_name.addr, rout_len);
+ memcpy(&obj_name[rout_len], DOTOBJ, SIZEOF(DOTOBJ)); /* includes null terminator */
+ pblk.def1_size = rout_len + SIZEOF(DOTOBJ) - 1; /* Length does not include null terminator */
+ pblk.def1_buf = obj_name;
+ status = parse_file(&fstr, &pblk);
+ if (0 == (status & 1))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, fstr.len, fstr.addr, status);
+
+ object_name_len = pblk.b_esl;
+ object_file_name[object_name_len] = '\0';
+}
diff --git a/sr_unix/parse_file.c b/sr_unix/parse_file.c
index 1030085..eace086 100644
--- a/sr_unix/parse_file.c
+++ b/sr_unix/parse_file.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -48,13 +48,12 @@ enum parse_state
SLASH
};
-GBLREF mval dollar_zdir;
+GBLREF mval dollar_zdir;
-int4 parse_file(mstr *file, parse_blk *pblk)
+int4 parse_file(mstr *file, parse_blk *pblk)
{
struct stat statbuf;
- struct addrinfo *ai_ptr = NULL, *localhost_ai_ptr = NULL, *temp_ai_ptr = NULL;
- struct addrinfo hints;
+ struct addrinfo *ai_ptr, *localhost_ai_ptr, *temp_ai_ptr, hints;
mstr trans, tmp;
int status, diff, local_node_len, query_node_len, node_name_len;
parse_blk def;
@@ -70,6 +69,7 @@ int4 parse_file(mstr *file, parse_blk *pblk)
int errcode;
pblk->fnb = 0;
+ ai_ptr = localhost_ai_ptr = temp_ai_ptr = NULL;
assert(((unsigned int)pblk->buff_size + 1) <= (MAX_FBUFF + 1));
/* All callers of parse_blk set buff_size to 1 less than the allocated buffer. This is because buff_size is a char
* type (for historical reasons) and so cannot go more than 255 whereas we support a max of 255 characters. So we
@@ -80,8 +80,7 @@ int4 parse_file(mstr *file, parse_blk *pblk)
if (SS_LOG2LONG == status)
return ERR_PARBUFSM;
assert(trans.addr == pblk->buffer);
-
- memset(&def, 0, SIZEOF(def)); /* initial the defaults to zero */
+ memset(&def, 0, SIZEOF(def)); /* Initial the defaults to zero */
if (pblk->def1_size > 0)
{ /* Parse default filespec if supplied */
def.fop = F_SYNTAXO;
@@ -93,22 +92,20 @@ int4 parse_file(mstr *file, parse_blk *pblk)
tmp.addr = pblk->def1_buf;
if ((status = parse_file(&tmp, &def)) != ERR_PARNORMAL)
return status;
-
assert(!def.b_node);
if (def.b_dir) def.fnb |= F_HAS_DIR;
if (def.b_name) def.fnb |= F_HAS_NAME;
if (def.b_ext) def.fnb |= F_HAS_EXT;
}
-
wildname = wilddir = hasnode = hasdir = hasname = hasext = FALSE;
node = base = ptr = trans.addr;
top = ptr + trans.len;
- if (trans.len == 0 || *ptr != '/')
+ if ((0 == trans.len) || ('/' != *ptr))
{ /* No file given, no full path given, or a nodename was specified */
setzdir(NULL, &def_trans); /* Default current directory if none given */
- assert(0 == dollar_zdir.str.len || /* dollar_zdir not initialized yet, possible thru main() -> gtm_chk_dist() */
- (def_trans.str.len == dollar_zdir.str.len && /* check if cwd and cached value are the same */
- 0 == memcmp(def_trans.str.addr, dollar_zdir.str.addr, def_trans.str.len)));
+ assert((0 == dollar_zdir.str.len) /* dollar_zdir not initialized yet, possible thru main() -> gtm_chk_dist() */
+ || ((def_trans.str.len == dollar_zdir.str.len) /* Check if cwd and cached value are the same */
+ && (0 == memcmp(def_trans.str.addr, dollar_zdir.str.addr, def_trans.str.len))));
if (pblk->fop & F_PARNODE)
{ /* What we have could be a nodename */
assert(pblk->fop & F_SYNTAXO);
@@ -123,32 +120,30 @@ int4 parse_file(mstr *file, parse_blk *pblk)
break;
}
}
-
if (node < top)
{
hasnode = TRUE;
- ptr = base = node; /* Update pointers past node name */
-
+ ptr = base = node; /* Update pointers past node name */
/* See if the desired (query) node is the local node */
node_name_len = (int)(node - trans.addr); /* Scanned node including ':' */
- query_node_len = node_name_len - 1; /* Pure name length, no ':' on end */
+ query_node_len = node_name_len - 1; /* Pure name length, no ':' on end */
assert(MAX_HOST_NAME_LEN >= query_node_len);
assert(0 < query_node_len);
assert(':' == *(trans.addr + query_node_len));
memcpy(query_node_name, trans.addr, query_node_len);
query_node_name[query_node_len] = 0;
- localhost_sa_ptr = NULL; /* null value needed if not find query node (remote default) */
+ localhost_sa_ptr = NULL; /* Null value needed if not find query node (remote default) */
CLIENT_HINTS(hints);
- if (0 != (errcode = getaddrinfo(query_node_name, NULL, &hints, &ai_ptr)))
- ai_ptr = NULL; /* skip additional lookups */
+ if (0 != (errcode = getaddrinfo(query_node_name, NULL, &hints, &ai_ptr))) /* Assignment! */
+ ai_ptr = NULL; /* Skip additional lookups */
else
memcpy((sockaddr_ptr)&query_sas, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
CLIENT_HINTS(hints);
- if (0 == (errcode = getaddrinfo(LOCALHOSTNAME, NULL, &hints, &localhost_ai_ptr)))
+ if (0 == (errcode = getaddrinfo(LOCALHOSTNAME, NULL, &hints, &localhost_ai_ptr))
+ && (0 == memcmp(localhost_ai_ptr->ai_addr, (sockaddr_ptr)&query_sas,
+ localhost_ai_ptr->ai_addrlen)))
{
- if (0 == memcmp(localhost_ai_ptr->ai_addr, (sockaddr_ptr)&query_sas,
- localhost_ai_ptr->ai_addrlen))
- localhost_sa_ptr = localhost_ai_ptr->ai_addr;
+ localhost_sa_ptr = localhost_ai_ptr->ai_addr;
}
FREEADDRINFO(localhost_ai_ptr);
if (ai_ptr && !localhost_sa_ptr)
@@ -159,7 +154,7 @@ int4 parse_file(mstr *file, parse_blk *pblk)
LEN_AND_LIT("gethostname"), CALLFROM, errno);
CLIENT_HINTS(hints);
if (0 != (errcode = getaddrinfo(local_node_name, NULL, &hints, &localhost_ai_ptr)))
- localhost_ai_ptr = NULL; /* empty address list */
+ localhost_ai_ptr = NULL; /* Empty address list */
for (temp_ai_ptr = localhost_ai_ptr; temp_ai_ptr!= NULL;
temp_ai_ptr = temp_ai_ptr->ai_next)
{
@@ -176,7 +171,7 @@ int4 parse_file(mstr *file, parse_blk *pblk)
{
CLIENT_HINTS(hints);
if (0 != (errcode = getaddrinfo(LOCALHOSTNAME6, NULL, &hints, &localhost_ai_ptr)))
- localhost_ai_ptr = NULL; /* empty address list */
+ localhost_ai_ptr = NULL; /* Empty address list */
for (temp_ai_ptr = localhost_ai_ptr; temp_ai_ptr!= NULL;
temp_ai_ptr = temp_ai_ptr->ai_next)
{
@@ -216,11 +211,9 @@ int4 parse_file(mstr *file, parse_blk *pblk)
node = trans.addr;
}
}
-
/* If parse buffer is not large enough, return error */
if (def_trans.str.len + trans.len > pblk->buff_size)
return ERR_PARBUFSM;
-
/* Construct full filename to parse prefixing given filename with default path prefix */
if (0 < def_trans.str.len)
{
@@ -231,10 +224,9 @@ int4 parse_file(mstr *file, parse_blk *pblk)
top += def_trans.str.len;
}
}
-
name = ptr;
state = NOSTATE;
- for (;ptr < top;)
+ for (; ptr < top;)
{
ch = *ptr;
if ('.' == ch)
@@ -244,14 +236,12 @@ int4 parse_file(mstr *file, parse_blk *pblk)
} else if (ch == '/')
{ /* We must still be doing the path */
ptr++;
-
hasdir = TRUE;
hasname = FALSE;
hasext = FALSE;
wilddir |= wildname;
wildname = FALSE;
-
- if (DOT1 != state && DOT2 != state && SLASH != state)
+ if ((DOT1 != state) && (DOT2 != state) && (SLASH != state))
{ /* No dots seen recently so scan as if this is start of filename */
state = SLASH;
name = ptr;
@@ -270,12 +260,12 @@ int4 parse_file(mstr *file, parse_blk *pblk)
while ('/' != *del)
del--;
}
- assert(del >= base && '/' == *del);
+ assert((del >= base) && ('/' == *del));
del++;
} else if (SLASH == state)
{ /* Remove duplicate slash from path */
del = ptr - 1;
- while (ptr < top && '/' == *ptr)
+ while ((ptr < top) && ('/' == *ptr))
ptr++;
}
memmove(del, ptr, top - ptr);
@@ -296,7 +286,7 @@ int4 parse_file(mstr *file, parse_blk *pblk)
{/* Filename has an extension */
hasext = TRUE;
ext = ptr;
- } else if ('?' == ch || '*' == ch)
+ } else if (('?' == ch) || ('*' == ch))
wildname = TRUE;
ptr++;
}
@@ -304,7 +294,7 @@ int4 parse_file(mstr *file, parse_blk *pblk)
}
}
/* Handle scan end with non-normal state */
- if (SLASH == state || DOT1 == state || DOT2 == state)
+ if ((SLASH == state) || (DOT1 == state) || (DOT2 == state))
{
assert(!hasname && !hasext);
hasdir = TRUE;
@@ -314,22 +304,21 @@ int4 parse_file(mstr *file, parse_blk *pblk)
ptr--;
}
if (DOT2 == state)
- { /* ignore ../ plus last directory level specified */
+ { /* Ignore ../ plus last directory level specified */
del = ptr - 3; /* on the end */
assert ('/' == *del);
if (del > base)
{
del--;
- while ('/' == *del)
+ while ('/' != *del)
del--;
}
- assert(del >= base && '/' == *del);
+ assert((del >= base) && ('/' == *del));
del++;
ptr = top = del;
name = ptr;
}
}
-
if (!hasname)
{
assert(!hasext);
@@ -358,8 +347,7 @@ int4 parse_file(mstr *file, parse_blk *pblk)
}
pblk->b_name = ext - name;
pblk->b_ext = ptr - ext;
-
- if (!hasdir && (def.fnb & F_HAS_DIR))
+ if (!hasdir && (def.fnb & F_HAS_DIR))
{
diff = (int)(name - base);
diff = def.b_dir - diff;
@@ -378,13 +366,11 @@ int4 parse_file(mstr *file, parse_blk *pblk)
pblk->l_dir = base;
pblk->l_name = base + pblk->b_dir;
pblk->l_ext = pblk->l_name + pblk->b_name;
-
pblk->fnb |= (hasdir << V_HAS_DIR);
pblk->fnb |= (hasname << V_HAS_NAME);
pblk->fnb |= (hasext << V_HAS_EXT);
pblk->fnb |= (wildname << V_WILD_NAME);
pblk->fnb |= (wilddir << V_WILD_DIR);
-
if (!(pblk->fop & F_SYNTAXO) && !wilddir)
{
assert('/' == pblk->l_dir[pblk->b_dir - 1]);
@@ -393,10 +379,9 @@ int4 parse_file(mstr *file, parse_blk *pblk)
pblk->l_dir[pblk->b_dir - 1] = 0;
STAT_FILE(pblk->l_dir, &statbuf, status);
pblk->l_dir[pblk->b_dir - 1] = '/';
- if (-1 == status || !(statbuf.st_mode & S_IFDIR))
+ if ((-1 == status) || !(statbuf.st_mode & S_IFDIR))
return ERR_FILENOTFND;
}
}
-
return ERR_PARNORMAL;
}
diff --git a/sr_unix/parse_file.h b/sr_unix/parse_file.h
index b33a5b8..0dffb0d 100644
--- a/sr_unix/parse_file.h
+++ b/sr_unix/parse_file.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -9,29 +9,29 @@
* *
****************************************************************/
-#define MAX_FBUFF 255 /* max file size (why different from MAX_PATH[_LEN]? */
+#define MAX_FBUFF 255 /* Max file size (why different from MAX_PATH[_LEN]/GTM_PATH_MAX ? */
#define DEF_DBEXT "*.dat"
#define DEF_NODBEXT "*"
typedef struct parse_blk_struct
{
- unsigned char b_esl; /* resultant name length */
- unsigned char b_node; /* length of node name at front - db opening only */
- unsigned char b_dir; /* length of directory path */
- unsigned char b_name; /* length of file name */
- unsigned char b_ext; /* length of extension */
- unsigned char def1_size; /* default 1 string size */
- char *def1_buf; /* default 1 buffer */
- unsigned char def2_size; /* default 1 string size */
- char *def2_buf; /* default 1 buffer */
- unsigned char buff_size; /* result buffer size */
- char *buffer; /* result buffer */
- int4 fnb; /* parse result characteristics */
- int4 fop; /* parse options SYNTAX_ONLY only */
- char *l_node, /* pointer to node specification - db opening only */
- *l_dir, /* pointer to directory path string */
- *l_name, /* pointer to file name string */
- *l_ext; /* pointer to extension string */
+ unsigned char b_esl; /* Resultant name length */
+ unsigned char b_node; /* Length of node name at front - db opening only */
+ unsigned char b_dir; /* Length of directory path */
+ unsigned char b_name; /* Length of file name */
+ unsigned char b_ext; /* Length of extension */
+ unsigned char def1_size; /* Default 1 string size */
+ char *def1_buf; /* Default 1 buffer */
+ unsigned char def2_size; /* Default 2 string size */
+ char *def2_buf; /* Default 2 buffer */
+ unsigned char buff_size; /* Result buffer size */
+ char *buffer; /* Result buffer */
+ int4 fnb; /* Parse result characteristics */
+ int4 fop; /* Parse options SYNTAX_ONLY only */
+ char *l_node, /* Pointer to node specification - db opening only */
+ *l_dir, /* Pointer to directory path string */
+ *l_name, /* Pointer to file name string */
+ *l_ext; /* Pointer to extension string */
} parse_blk;
typedef struct plength_struct
@@ -41,30 +41,30 @@ typedef struct plength_struct
int4 pint;
struct
{
- unsigned char b_esl; /* resultant name length */
- unsigned char b_dir; /* length of directory path */
- unsigned char b_name; /* length of file name */
- unsigned char b_ext; /* length of extension */
+ unsigned char b_esl; /* Resultant name length */
+ unsigned char b_dir; /* Length of directory path */
+ unsigned char b_name; /* Length of file name */
+ unsigned char b_ext; /* Length of extension */
} pblk;
} p;
} plength;
-#define F_HAS_EXT 1 /* if file has explicit extension */
-#define F_HAS_NAME 2 /* if file has explicit name */
-#define F_HAS_DIR 4 /* if file has explicit directory path */
-#define F_WILD_NAME 8 /* if there is a wild card character in the name */
-#define F_WILD_DIR 16 /* if there is a wild card character in the directory */
-#define F_WILD 24 /* if there is a wild card character in the result */
-#define F_HAS_NODE 32 /* if there is a node specification on the front - db opening only */
+#define F_HAS_EXT 1 /* 0x01 If file has explicit extension */
+#define F_HAS_NAME 2 /* 0x02 If file has explicit name */
+#define F_HAS_DIR 4 /* 0x04 If file has explicit directory path */
+#define F_WILD_NAME 8 /* 0x08 If there is a wild card character in the name */
+#define F_WILD_DIR 16 /* 0x10 If there is a wild card character in the directory */
+#define F_WILD 24 /* 0x20 If there is a wild card character in the result */
+#define F_HAS_NODE 32 /* 0x40 If there is a node specification on the front - db opening only */
-#define V_HAS_EXT 0 /* bit offsets for F_ constants */
+#define V_HAS_EXT 0 /* Bit offsets for F_ constants */
#define V_HAS_NAME 1
#define V_HAS_DIR 2
#define V_WILD_NAME 3
#define V_WILD_DIR 4
-#define V_HAS_NODE 5 /* db opening only */
+#define V_HAS_NODE 5 /* DB opening only */
#define F_SYNTAXO 1 /* SYNTAX ONLY */
-#define F_PARNODE 2 /* look for a node specification - db opening only */
+#define F_PARNODE 2 /* Look for a node specification - db opening only */
int4 parse_file(mstr *file, parse_blk *pblk);
diff --git a/sr_unix/pinentry.m b/sr_unix/pinentry.m
index f0961db..678ccb1 100644
--- a/sr_unix/pinentry.m
+++ b/sr_unix/pinentry.m
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2010, 2013 Fidelity Information Services, Inc ;
+; Copyright 2010, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -13,18 +13,19 @@ pinentry ; Substitute pinentry that returns an unobfuscated password
; if $gtm_passwd is defined in the environment. If the command
; received is not GETPIN, this runs /usr/bin/pinentry
;
- Set $ETrap="Write $ZStatus,!,$Stack($Stack,""MCODE""),! Halt"
- Set obfpwd=$ZTRNLNM("gtm_passwd"),obfpwdlen=$Length(obfpwd)
- Write "OK Your orders please",!
- Set done=0
- For Quit:done Read in Quit:'$Length(in) Do
- . If "GETPIN"=$Translate($Piece(in," ",1),"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ") Do
- . . Set obfpwds=""
- . . For i=1:2:$Length(obfpwd) Do
- . . . Set msb=$Find("0123456789ABCDEF",$Extract(obfpwd,i))-2
- . . . Set lsb=$Find("0123456789ABCDEF",$Extract(obfpwd,i+1))-2
- . . . Set obfpwds=obfpwds_$ZCHar(16*msb+lsb)
- . . Write:'$&gpgagent.unmaskpwd(obfpwds,.clrpwds) "D ",clrpwds,!
- . . Set done=1
- . Write "OK",!
- Quit
+ set $etrap="write $zstatus,!,$stack($stack,""MCODE""),! halt"
+ set obfpwd=$ztrnlnm("gtm_passwd"),obfpwdlen=$length(obfpwd)
+ set obfpwd=$zconvert(obfpwd,"U")
+ write "OK Your orders please",!
+ set done=0
+ for quit:done read in quit:'$length(in) do
+ . if "GETPIN"=$zconvert($piece(in," ",1),"U") do
+ . . set obfpwds=""
+ . . for i=1:2:$length(obfpwd) do
+ . . . set msb=$find("0123456789ABCDEF",$extract(obfpwd,i))-2
+ . . . set lsb=$find("0123456789ABCDEF",$extract(obfpwd,i+1))-2
+ . . . set obfpwds=obfpwds_$zchar(16*msb+lsb)
+ . . write:'$&gpgagent.unmaskpwd(obfpwds,.clrpwds) "D ",clrpwds,!
+ . . set done=1
+ . write "OK",!
+ quit
diff --git a/sr_unix/reg_cmcheck.c b/sr_unix/reg_cmcheck.c
index 1ddb0ef..a1fb56e 100644
--- a/sr_unix/reg_cmcheck.c
+++ b/sr_unix/reg_cmcheck.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,6 +21,8 @@
#define MAX_NODE_NAME 32
+error_def(ERR_DBFILERR);
+
bool reg_cmcheck(gd_region *reg)
{
gd_segment *seg;
@@ -28,9 +30,10 @@ bool reg_cmcheck(gd_region *reg)
parse_blk pblk;
mstr file;
int status;
- error_def(ERR_DBFILERR);
seg = reg->dyn.addr;
+ if (dba_cm == seg->acc_meth)
+ return TRUE; /* if access method has already been set to dba_cm, return right away (avoid recomputation) */
file.addr = (char *)seg->fname;
file.len = seg->fname_len;
memset(&pblk, 0, SIZEOF(pblk));
@@ -43,17 +46,14 @@ bool reg_cmcheck(gd_region *reg)
{
pblk.def1_buf = DEF_NODBEXT;
pblk.def1_size = SIZEOF(DEF_NODBEXT) - 1;
- }
- else
+ } else
{
pblk.def1_buf = DEF_DBEXT;
pblk.def1_size = SIZEOF(DEF_DBEXT) - 1;
}
-
status = parse_file(&file, &pblk);
if (!(status & 1))
- rts_error(VARLSTCNT(5) ERR_DBFILERR,2, seg->fname_len, seg->fname, status);
-
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_DBFILERR,2, seg->fname_len, seg->fname, status);
assert((int)pblk.b_esl + 1 <= SIZEOF(seg->fname));
memcpy(seg->fname, pblk.buffer, pblk.b_esl);
pblk.buffer[pblk.b_esl] = 0;
@@ -62,6 +62,7 @@ bool reg_cmcheck(gd_region *reg)
if (pblk.fnb & F_HAS_NODE)
{
assert(pblk.b_node && ':' == pblk.l_node[pblk.b_node - 1]);
+ seg->acc_meth = dba_cm;
return TRUE;
}
return FALSE;
diff --git a/sr_unix/relinkctl.c b/sr_unix/relinkctl.c
new file mode 100644
index 0000000..3ea1596
--- /dev/null
+++ b/sr_unix/relinkctl.c
@@ -0,0 +1,468 @@
+/****************************************************************
+ * *
+ * Copyright 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include "gtm_limits.h"
+#include "gtm_fcntl.h"
+#include "gtm_unistd.h"
+#include "gtm_stdlib.h"
+#include "gtm_stdio.h"
+#include "gtm_string.h"
+#include "gtm_stat.h"
+
+#include "add_inter.h"
+#include "interlock.h"
+#include "gtmio.h"
+#include <rtnhdr.h>
+#include "relinkctl.h"
+#include "zhist.h"
+#include "md5hash.h"
+#include "md5_digest2hex.h"
+#include "stringpool.h"
+
+/*
+ * This module contains routines that maintain autorelink 'relinkctl' structures.
+ * TODO - add description
+ */
+
+DEBUG_ONLY(GBLDEF int saved_errno;)
+GBLREF uint4 process_id;
+
+STATICFNDCL void relinkctl_map(open_relinkctl_sgm *linkctl, uint4 n_records);
+STATICFNDCL void relinkctl_unmap(open_relinkctl_sgm *linkctl);
+STATICFNDCL uint4 relinkctl_recs2map(uint4 n_records);
+STATICFNDCL int relinkctl_fcntl_lock(int fd, int l_type);
+STATICFNDCL void relinkctl_get_key(char key[GTM_PATH_MAX], mstr *zro_entry_name);
+STATICFNDCL void relinkctl_delete(open_relinkctl_sgm *linkctl);
+
+#define ISSUE_RELINKCTLERR_SYSCALL(ZRO_ENTRY_NAME, LIBCALL) \
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(12) ERR_RELINKCTLERR, 2, RTS_ERROR_MSTR(ZRO_ENTRY_NAME), \
+ ERR_SYSCALL, 5, LEN_AND_STR(LIBCALL), CALLFROM, DEBUG_ONLY(saved_errno = )errno)
+
+error_def(ERR_RELINKCTLERR);
+error_def(ERR_SYSCALL);
+error_def(ERR_TEXT);
+
+/* Routine called to see if a relinkctl structure already exists for the given zroutines element.
+ *
+ * Parameters:
+ * - obj_container_name - object container name string
+ *
+ * Output:
+ * - Found or newly created private structure which points to shared relink control structure
+ */
+open_relinkctl_sgm *relinkctl_attach(mstr *obj_container_name)
+{
+ open_relinkctl_sgm *linkctl, *new_link;
+ int len, save_errno;
+ mstr objdir;
+ char pathin[GTM_PATH_MAX], resolvedpath[GTM_PATH_MAX]; /* Includes null terminator char */
+ char *pathptr;
+ boolean_t pathfound;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+# ifdef USHBIN_SUPPORTED
+ /* Directory name normalization - the directory name must always be the same for purposes of mapping the relinkctl
+ * file. To accomplish this takes two steps:
+ * 1. Use realpath() on the directory name to disambiguate it.
+ * 2. Remove trailing slash(es) in the object directory name.
+ */
+ pathfound = TRUE; /* Assume we'll find the path */
+ assert(GTM_PATH_MAX > obj_container_name->len); /* Should have been checked by our caller */
+ memcpy(pathin, obj_container_name->addr, obj_container_name->len);
+ pathin[obj_container_name->len] = '\0'; /* Needs null termination for realpath call */
+ pathptr = realpath(pathin, resolvedpath);
+ if (NULL == pathptr)
+ {
+ pathfound = FALSE; /* Path no longer exists - use our best attempt to find it */
+ pathptr = pathin;
+ }
+ objdir.addr = pathptr;
+ objdir.len = strlen(pathptr);
+ while ((1 < objdir.len) && ('/' == *(objdir.addr + objdir.len - 1)))
+ objdir.len--;
+ /* Now look the directory up in our list to see if we have it or not already */
+ for (linkctl = TREF(open_relinkctl_list); NULL != linkctl; linkctl = linkctl->next)
+ {
+ if (MSTR_EQ(&objdir, &linkctl->zro_entry_name))
+ return linkctl;
+ }
+ /* If realpath() didn't find the path and we don't already have it open, don't create a relinkctl file for it */
+ if (!pathfound)
+ return NULL;
+ /* Not already open */
+ new_link = malloc(SIZEOF(open_relinkctl_sgm));
+ new_link->zro_entry_name = objdir;
+ s2pool(&new_link->zro_entry_name); /* Migrate string to stringpool for safe keeping */
+ /* Open + map structure */
+ relinkctl_open(new_link);
+ /* Add to open list */
+ new_link->next = TREF(open_relinkctl_list);
+ TREF(open_relinkctl_list) = new_link;
+ return new_link;
+# else
+ return NULL;
+# endif
+
+}
+
+/*
+ * Given linkctl->zro_entry_name -- an object directory in $ZROUTINES -- open() and mmap() relink ctl structure, thus
+ * filling in linkctl->fd and linkctl->hdr.
+ * The control structure should be both readable *and* writable by anything that can read the object directory.
+ */
+void relinkctl_open(open_relinkctl_sgm *linkctl)
+{
+ int fd, status, save_errno;
+ int umask_creat, umask_orig;
+ char relinkctl_path[GTM_PATH_MAX];
+ struct stat stat_buf;
+
+# ifdef USHBIN_SUPPORTED
+ linkctl->hdr = NULL;
+ /* open the given relinkctl file */
+ relinkctl_get_key(relinkctl_path, &linkctl->zro_entry_name);
+ DBGARLNK((stderr, "relinkctl_open: Opening relinkctl file %s for entry %.*s\n", relinkctl_path,
+ linkctl->zro_entry_name.len, linkctl->zro_entry_name.addr));
+ /* RW permissions for owner and others as determined by umask. */
+ umask_orig = umask(000); /* determine umask (destructive) */
+ (void)umask(umask_orig); /* reset umask */
+ umask_creat = 0666 & ~umask_orig;
+ /* Anybody that has read permissions to the object container should have write permissions to the relinkctl file */
+ fd = OPEN3(relinkctl_path, O_CREAT | O_RDWR, umask_creat);
+ /* TODO: get permissions right. see comment above . important */
+ /* Do we want a relinkctl sitting around for $gtm_dist? */
+ if (FD_INVALID == fd)
+ ISSUE_RELINKCTLERR_SYSCALL(&linkctl->zro_entry_name, "open()");
+ linkctl->fd = fd;
+ /* If file is newly created, initialize it */
+ FSTAT_FILE(fd, &stat_buf, status);
+ if (0 != status)
+ ISSUE_RELINKCTLERR_SYSCALL(&linkctl->zro_entry_name, "fstat()");
+ if (0 == stat_buf.st_size)
+ {
+ relinkctl_lock_exclu(linkctl);
+ FSTAT_FILE(fd, &stat_buf, status);
+ if (0 != status)
+ {
+ relinkctl_unlock_exclu(linkctl);
+ ISSUE_RELINKCTLERR_SYSCALL(&linkctl->zro_entry_name, "fstat()");
+ }
+ if (0 == stat_buf.st_size)
+ {
+ /* TODO: fix file extension so we don't need to preallocate so much space */
+ ftruncate(fd, SIZEOF(relinkctl_data) + 1000000 * SIZEOF(relinkrec_t));
+ relinkctl_map(linkctl, 0);
+ linkctl->hdr->n_records = 0; /* what happens if kill -9'd between ftruncate and n_records = 0? */
+ SET_LATCH_GLOBAL(&linkctl->hdr->attach_latch, LOCK_AVAILABLE);
+ relinkctl_unmap(linkctl);
+ }
+ relinkctl_unlock_exclu(linkctl);
+ }
+ /* Do an small mapping in order to read n_records, then map the full file */
+ relinkctl_map(linkctl, 0);
+ relinkctl_ensure_fullmap(linkctl);
+ /* Need lock to prevent interaction with concurrent initialization, nattached = 0 */
+ relinkctl_lock_exclu(linkctl);
+ linkctl->hdr->nattached++;
+ /*sprintf(buff, "%s - incremented. nattached = %d", linkctl->zro_entry_name, linkctl->hdr->nattached);
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2, LEN_AND_STR(buff));*/
+ /*send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2,
+ LEN_AND_LIT("%s - incremented. nattached = %d")); debugging TODO*/
+ relinkctl_unlock_exclu(linkctl);
+ /* TODO: when to close? with ZGOTO 0? or never bother? */
+# endif
+}
+
+/* Routine to generate unique key for a $ZROUTINES entry name used to create relinkctl file for that entry in the directory
+ * $gtm_linktmpdir (e.g. /testarea1/gtm/temp --> $gtm_linktmpdir/gtm-relinkctl-d0f3d074c724430bc1c7679141b96411).
+ * Theoretically, we'd need a scheme to resolve hash collisions. Say, append -<collision_id> to the key.
+ * But since this is MD5, we can assume a collision will never happen in practice, so we do not handle the extremely
+ * unlikely event of an MD5 hash collision for the few $ZROUTINES entries used by processes using the same $gtm_linktmpdir
+ * value.
+ *
+ * Parameters:
+ *
+ * key - Generated as $gtm_linktmpdir/gtm-relinkctl-<md5>. Buffer should be GTM_PATH_MAX bytes (output).
+ * zro_entry_name - Address of mstr containing the fully expanded zroutines entry directory name.
+ */
+#ifdef USHBIN_SUPPORTED
+STATICFNDEF void relinkctl_get_key(char key[GTM_PATH_MAX], mstr *zro_entry_name)
+{
+ cvs_MD5_CTX md5context;
+ unsigned char digest[MD5_DIGEST_LENGTH];
+ char hexstr[MD5_HEXSTR_LENGTH];
+ int keylen;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ cvs_MD5Init(&md5context);
+ cvs_MD5Update(&md5context, (const unsigned char *)zro_entry_name->addr, zro_entry_name->len);
+ cvs_MD5Final(digest, &md5context);
+ md5_digest2hex(hexstr, digest);
+ /* Improve efficiency - use memcpy to build string and provide better max-length checking than an assert */
+ keylen = SNPRINTF(&key[0], GTM_PATH_MAX - 1, "%.*s/gtm-relinkctl-%s", (TREF(gtm_linktmpdir)).len,
+ (TREF(gtm_linktmpdir)).addr, hexstr);
+ assert((0 < keylen) && (GTM_PATH_MAX > keylen));
+}
+#endif
+
+/**
+ * Relinkctl mmap-related methods
+ */
+
+/*
+ * Remap, if entire array of relink records is not mapped.
+ */
+void relinkctl_ensure_fullmap(open_relinkctl_sgm *linkctl)
+{
+ uint4 nrec;
+
+# ifdef USHBIN_SUPPORTED
+ nrec = linkctl->hdr->n_records;
+ if (nrec >= relinkctl_recs2map(linkctl->n_records))
+ {
+ relinkctl_unmap(linkctl);
+ relinkctl_map(linkctl, nrec);
+ }
+ linkctl->n_records = nrec;
+# endif
+}
+
+/*
+ * Map at least n_records, currently known number of entries.
+ *
+ * Fills in:
+ * linkctl->hdr
+ * linkctl->n_records
+ * linkctl->rec_base
+ */
+#ifdef USHBIN_SUPPORTED
+STATICFNDEF void relinkctl_map(open_relinkctl_sgm *linkctl, uint4 n_records)
+{
+ sm_uc_ptr_t addr;
+ size_t mapsz;
+
+ mapsz = SIZEOF(relinkctl_data) + (relinkctl_recs2map(n_records) * SIZEOF(relinkrec_t));
+ addr = (sm_uc_ptr_t)mmap(NULL, mapsz, (PROT_READ + PROT_WRITE), MAP_SHARED, linkctl->fd, 0);
+ if (MAP_FAILED == addr)
+ ISSUE_RELINKCTLERR_SYSCALL(&linkctl->zro_entry_name, "mmap()");
+ linkctl->hdr = (relinkctl_data *)addr;
+ linkctl->n_records = n_records;
+ linkctl->rec_base = &linkctl->hdr->base[0];
+}
+
+STATICFNDEF void relinkctl_unmap(open_relinkctl_sgm *linkctl)
+{
+ /* TODO */
+}
+
+/*
+ * We don't want to repeatedly re-mmap the file, so given some minimum number of records we need to map,
+ * compute a larger number to accomodate before we need to remap.
+ */
+STATICFNDEF uint4 relinkctl_recs2map(uint4 n_records)
+{
+ /* TODO: Improve - right now, limited to fixed initial size */
+ return 1000000;
+ /* return n_records + 1; - This causes excessive remapping - pick a better increment */
+}
+#endif
+
+/**
+ * Exclusive locking methods controlling WRITE access to relinkctl control files.
+ */
+
+/*
+ * Routine to exclusively lock the relinkctl file.
+ *
+ * Parameter:
+ *
+ * linkctl - address of relink control structure for a given $ZROUTINEs node
+ */
+void relinkctl_lock_exclu(open_relinkctl_sgm *linkctl)
+{
+ int status;
+
+# ifdef USHBIN_SUPPORTED
+ status = relinkctl_fcntl_lock(linkctl->fd, F_WRLCK);
+ assert(0 == status); /* TODO: Deal with error */
+ linkctl->locked = TRUE;
+# endif
+ return;
+}
+
+void relinkctl_unlock_exclu(open_relinkctl_sgm *linkctl)
+{
+ int status;
+
+# ifdef USHBIN_SUPPORTED
+ status = relinkctl_fcntl_lock(linkctl->fd, F_UNLCK);
+ assert(0 == status); /* TODO: Deal with error */
+ linkctl->locked = FALSE;
+# endif
+ return;
+}
+
+/* Routine to set or remove an advisory lock on a given relinkctl file.
+ *
+ * Parameters:
+ *
+ * fd - File descriptor of file to lock.
+ * l_type - Lock type (F_WRLCK for lock or F_UNLCK for unlock)
+ *
+ * Return value:
+ *
+ * - status of fcntl() lock or unlock attempt
+ */
+#ifdef USHBIN_SUPPORTED
+STATICFNDEF int relinkctl_fcntl_lock(int fd, int l_type)
+{
+ int status;
+ struct flock lock;
+
+ assert((F_WRLCK == l_type) || (F_UNLCK == l_type));
+ do
+ {
+ lock.l_type = l_type;
+ lock.l_whence = SEEK_SET; /* Locking offsets from file beginning */
+ lock.l_start = lock.l_len = 0; /* Lock the whole file */
+ lock.l_pid = process_id;
+ } while ((-1 == (status = fcntl(fd, F_SETLKW, &lock))) && (EINTR == errno));
+ return status;
+}
+#endif
+
+/**
+ * Relinkctl file record management routines
+ */
+
+/* Like relinkctl_find_record, but inserts a new entry instead of returning REC_NOT_FOUND.
+ */
+relinkrec_loc_t relinkctl_insert_record(open_relinkctl_sgm *linkctl, mstr *rtnname)
+{
+ relinkrec_loc_t rec;
+ relinkrec_ptr_abs_t base, newrec;
+
+# ifdef USHBIN_SUPPORTED
+ rec = relinkctl_find_record(linkctl, rtnname);
+ if (REC_NOT_FOUND == rec)
+ {
+ relinkctl_lock_exclu(linkctl);
+ rec = relinkctl_find_record(linkctl, rtnname);
+ if (REC_NOT_FOUND == rec)
+ { /* File expansion scenario - TODO - don't assume additional record is available */
+ assert(linkctl->locked);
+ assert(linkctl->n_records == linkctl->hdr->n_records);
+ base = linkctl->rec_base;
+ newrec = base + (UINTPTR_T)linkctl->n_records;
+ newrec->cycle = 1; /* Start at cycle 1 instead of 0 */
+ memset(&newrec->rtnname_fixed.c[0], 0, SIZEOF(mident_fixed));
+ assert(MAX_MIDENT_LEN >= rtnname->len);
+ memcpy(&newrec->rtnname_fixed.c[0], rtnname->addr, rtnname->len);
+ /* TODO: Insert record's AVL node into AVL tree or hash entry into htab */
+ linkctl->hdr->n_records++;
+ rec = RCTLABS2REL(newrec, base);
+ assert(rec == relinkctl_find_record(linkctl, rtnname));
+ }
+ relinkctl_unlock_exclu(linkctl);
+ }
+ return rec;
+# else
+ return 0;
+# endif
+}
+
+/*
+ * Iterate through each relink_record_struct starting at (relink_record_ptr)&linkctl->map_addr[0]
+ * Find rec s.t. rec->rtnname == rtnname, return offset of rec.
+ * Otherwise, return NOMATCH (defined 0xffff..).
+ */
+relinkrec_loc_t relinkctl_find_record(open_relinkctl_sgm *linkctl, mstr *rtnname)
+{
+ relinkrec_ptr_abs_t rec, base, top;
+
+# ifdef USHBIN_SUPPORTED
+ relinkctl_ensure_fullmap(linkctl); /* Make sure we search among all currently existing records */
+ base = linkctl->rec_base;
+ top = base + (UINTPTR_T)linkctl->n_records;
+ for (rec = base; rec < top; rec++)
+ { /* For each record, check routine name plus null trailer in fixed version */
+ if ((0 == memcmp(&rec->rtnname_fixed.c, rtnname->addr, rtnname->len))
+ && ('\0' == rec->rtnname_fixed.c[rtnname->len]))
+ return RCTLABS2REL(rec, base);
+ }
+# endif
+ return REC_NOT_FOUND;
+}
+
+/**
+ * Relinkctl file rundown routines
+ */
+
+/*
+ * Close all file descriptors associated with relinkctl structs, and (atomically) decrement nattached in file header.
+ */
+void relinkctl_rundown(boolean_t decr_attached)
+{
+# ifdef USHBIN_SUPPORTED
+ int rc;
+ open_relinkctl_sgm *linkctl;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ for (linkctl = TREF(open_relinkctl_list); NULL != linkctl; linkctl = linkctl->next)
+ {
+ if (decr_attached)
+ {
+ relinkctl_lock_exclu(linkctl);
+ linkctl->hdr->nattached--;
+ /*sprintf(buff, "%s - decremented. nattached = %d", linkctl->zro_entry_name, linkctl->hdr->nattached);
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2, LEN_AND_STR(buff));*/
+ /*send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2,
+ LEN_AND_STR(linkctl->zro_entry_name));
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2,
+ LEN_AND_LIT("decremented")); debugging TODO */
+ relinkctl_unlock_exclu(linkctl);
+ assert(0 <= linkctl->hdr->nattached);
+ if (0 == linkctl->hdr->nattached)
+ {
+ relinkctl_lock_exclu(linkctl);
+ if (0 == linkctl->hdr->nattached)
+ relinkctl_delete(linkctl);
+ }
+ }
+ CLOSEFILE_RESET(linkctl->fd, rc);
+ linkctl->hdr = NULL;
+ linkctl->rec_base = NULL;
+ }
+ TREF(open_relinkctl_list) = NULL;
+# endif
+ return;
+}
+
+/*
+ * Clean up (i.e. delete) relinkctl file
+ */
+#ifdef USHBIN_SUPPORTED
+STATICFNDEF void relinkctl_delete(open_relinkctl_sgm *linkctl)
+{
+ char relinkctl_path[GTM_PATH_MAX + 1];
+
+ relinkctl_get_key(relinkctl_path, &linkctl->zro_entry_name);
+ UNLINK(relinkctl_path);
+ return;
+}
+#endif
diff --git a/sr_unix/relinkctl.h b/sr_unix/relinkctl.h
new file mode 100644
index 0000000..8879242
--- /dev/null
+++ b/sr_unix/relinkctl.h
@@ -0,0 +1,101 @@
+/****************************************************************
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#ifndef RELINKCTL_H_INCLUDED
+#define RELINKCTL_H_INCLUDED
+
+
+/* For autorelink debugging, uncomment the line below */
+/* #define AUTORELINK_DEBUG */
+#if defined(AUTORELINK_DEBUG)
+# define DBGARLNK(x) DBGFPF(x)
+# define DBGARLNK_ONLY(x) x
+# include "gtm_stdio.h"
+# include "gtmio.h"
+#else
+# define DBGARLNK(x)
+# define DBGARLNK_ONLY(x)
+#endif
+
+#define MIN_RELINKCTL_MAPSZ 1024 /* bytes */
+#define REC_NOT_FOUND (relinkrec_loc_t)(-1)
+
+/* Macros for dealing with relative and absolute addresses and converting between them */
+#define RCTLABS2REL(ABSADR, BASEADR) ((relinkrec_loc_t)((UINTPTR_T)(ABSADR) - (UINTPTR_T)(BASEADR)))
+#define RCTLREL2ABS(RELADR, BASEADR) ((relinkrec_ptr_abs_t)((UINTPTR_T)(BASEADR) + (UINTPTR_T)(RELADR)))
+
+/* Macro to read the cycle# of a given relinkctl record */
+#define RELINKCTL_CYCLE_READ(LINKCTL, RECOFFSET) (((relinkrec_ptr_abs_t)(RCTLREL2ABS((RECOFFSET), (LINKCTL)->rec_base)))->cycle)
+/* Macro to bump the cycle# of a given relinkctl record */
+#define RELINKCTL_CYCLE_INCR(LINKCTL, RECOFFSET) (((relinkrec_ptr_abs_t)(RCTLREL2ABS((RECOFFSET), (LINKCTL)->rec_base)))->cycle++)
+
+/*
+ * Possible TODO as it relates to ensuring consistent code state:
+ * Along with cycle and rtnname, put MD5 checksum in record. When a process ZLINKs, ensure that checksum of object matches?
+ * something like:
+ * 1. open() object file, note rhdr->MD5
+ * 2. Note rec->MD5
+ * 3. Issue error if different (unless it's different because of concurrent ZRUPDATE, in which case repeat from step 1.)
+ */
+
+/* Shared structure - relink record in a relinkctl (mmap'd) file */
+typedef struct relinkrec_struct
+{
+ mident_fixed rtnname_fixed;
+ uint4 cycle;
+ /* TODO: Add hash or tree or sorted list lookup for speed */
+} relinkrec_t;
+
+/* Shared structure - relinkctl file header */
+typedef struct relinkctl_data_struct
+{
+ /* TODO: Add zro_entry_name, so that we can "rundown" or delete desired structs */
+ uint4 n_records;
+ int4 nattached; /* Number of processes currently attached. this is approximate, because if a process
+ * is kill 9'd, nattached is not decrememented.
+ * If nattached is 0 upon exiting, we can remove the file.
+ * TODO: Provide fancier cleanup scheme for kill 9. two options:
+ * 1. SYSV semaphore (as with the db). increment in open_relinkctl
+ * 2. When we want to cleanup (say mupip routine -rundown), execute 'fuser'
+ */
+ global_latch_t attach_latch;
+ relinkrec_t base[1];
+} relinkctl_data;
+
+typedef off_t relinkrec_ptr_rel_t; /* Relative offset of relinkrec */
+typedef relinkrec_t *relinkrec_ptr_abs_t; /* Absolute pointer to relinkrec */
+/* For now at least, use relative pointers as primary way of referring to shared relink records */
+typedef relinkrec_ptr_rel_t relinkrec_loc_t;
+
+/* Process private structure - describes a relinkctl file. Process private so can be linked into a list in $ZROUTINES order */
+typedef struct open_relinkctl_struct
+{
+ struct open_relinkctl_struct *next; /* List of open ctl structures, sorted by zro_entry_name */
+ mstr zro_entry_name; /* Text resident in stringpool */
+ int fd;
+ uint4 n_records; /* Private copy */
+ relinkctl_data *hdr; /* Base of mapped file */
+ relinkrec_t *rec_base;
+ boolean_t locked; /* TRUE if this process owns exclusive lock */
+} open_relinkctl_sgm;
+
+/*
+ * Prototypes
+ */
+open_relinkctl_sgm *relinkctl_attach(mstr *obj_container_name);
+relinkrec_loc_t relinkctl_find_record(open_relinkctl_sgm *linkctl, mstr *rtnname);
+relinkrec_loc_t relinkctl_insert_record(open_relinkctl_sgm *linkctl, mstr *rtnname);
+void relinkctl_open(open_relinkctl_sgm *linkctl);
+void relinkctl_ensure_fullmap(open_relinkctl_sgm *linkctl);
+void relinkctl_lock_exclu(open_relinkctl_sgm *linkctl);
+void relinkctl_unlock_exclu(open_relinkctl_sgm *linkctl);
+void relinkctl_rundown(boolean_t decr_attached);
+#endif /* RELINKCTL_H_INCLUDED */
diff --git a/sr_unix/remove_rms.c b/sr_unix/remove_rms.c
index be6757a..d9f0b65 100644
--- a/sr_unix/remove_rms.c
+++ b/sr_unix/remove_rms.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -15,8 +15,10 @@
#include "gtm_unistd.h"
#include "io.h"
+#include "gtm_limits.h"
#include "iormdef.h"
#include "gtmio.h"
+#include "gtmcrypt.h"
GBLREF io_log_name *io_root_log_name;
@@ -43,6 +45,10 @@ void remove_rms (io_desc *ciod)
CLOSEFILE_RESET(rm_ptr->read_fildes, rc); /* resets "rm_ptr->read_fildes" to FD_INVALID */
if (rm_ptr && (rm_ptr->read_filstr != NULL))
FCLOSE(rm_ptr->read_filstr, fclose_res);
+ if (rm_ptr && rm_ptr->input_encrypted && (GTMCRYPT_INVALID_KEY_HANDLE != rm_ptr->input_cipher_handle))
+ GTMCRYPT_REMOVE_CIPHER_CONTEXT(rm_ptr->input_cipher_handle);
+ if (rm_ptr && rm_ptr->output_encrypted && (GTMCRYPT_INVALID_KEY_HANDLE != rm_ptr->output_cipher_handle))
+ GTMCRYPT_REMOVE_CIPHER_CONTEXT(rm_ptr->output_cipher_handle);
if (ciod->newly_created && rm_ptr && !rm_ptr->pipe)
{
UNLINK(ciod->trans_name->dollar_io);
diff --git a/sr_unix/repl_instance.c b/sr_unix/repl_instance.c
index b7a3888..19c5336 100644
--- a/sr_unix/repl_instance.c
+++ b/sr_unix/repl_instance.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -1175,7 +1175,7 @@ boolean_t repl_inst_was_rootprimary(void)
* to be FALSE. Assert accordingly.
*/
assert(((NULL != jnlpool.jnlpool_dummy_reg) && jnlpool.jnlpool_dummy_reg->open)
- || jgbl.onlnrlbk || (jgbl.mur_rollback && ANTICIPATORY_FREEZE_AVAILABLE));
+ || jgbl.onlnrlbk || (jgbl.mur_rollback && INST_FREEZE_ON_ERROR_POLICY));
csa = &FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs;
ASSERT_VALID_JNLPOOL(csa);
assert(csa->now_crit);
diff --git a/sr_unix/repl_sem.h b/sr_unix/repl_sem.h
index 5ab2538..080e886 100644
--- a/sr_unix/repl_sem.h
+++ b/sr_unix/repl_sem.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006 Fidelity Information Services, Inc *
+ * Copyright 2006, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -27,8 +27,8 @@ typedef enum
{
JNL_POOL_ACCESS_SEM, /* For Startup / Shutdown / Options-change */
SRC_SERV_COUNT_SEM, /* Source sever holds it while alive */
+ RECV_SERV_STARTUP_SEM, /* records the # of MUPIP REPLIC -RECEIV -START commands in progress at any point in time */
DUMMY_SEM1, /* added just to make the number of semaphores same as in recvpool */
- DUMMY_SEM2, /* added just to make the number of semaphores same as in recvpool */
SOURCE_ID_SEM,
NUM_SRC_SEMS
} source_sem_type;
diff --git a/sr_unix/retain_list.txt b/sr_unix/retain_list.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/sr_unix/rtnhdr.h b/sr_unix/rtnhdr.h
index 9bbe6e8..aa173fb 100644
--- a/sr_unix/rtnhdr.h
+++ b/sr_unix/rtnhdr.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -69,8 +69,8 @@ typedef struct rhead_struct
* describing shared library resident routine and this is its handle.
* Note this is an 8 byte field on Tru64 (hence its position near top).
*/
- mstr src_full_name; /* (#) fully qualified path of routine source code */
- uint4 compiler_qlf; /* bit flags of compiler qualifiers used (see cmd_qlf.h) */
+ mstr src_full_name; /* (#) Fully qualified path of routine source code */
+ uint4 compiler_qlf; /* Bit flags of compiler qualifiers used (see cmd_qlf.h) */
uint4 objlabel; /* Object code level/label (see objlable.h).
* Note: this field must be the 10th word (11th on Tru64) on 32-bit
* environments so that incr_link() can deference object label from old
@@ -78,35 +78,45 @@ typedef struct rhead_struct
* situation wouldn't occur since dlopen() would/should have failed
* when a 32-bit shared library is loaded
*/
- mident routine_name; /* external routine name */
- var_tabent *vartab_adr; /* (#) address of variable table (offset in original rtnhdr) */
- int4 vartab_len; /* (#) number of variable table entries */
- lab_tabent *labtab_adr; /* address of label table (offset in original rtnhdr) */
- int4 labtab_len; /* number of label table entries */
- lnr_tabent *lnrtab_adr; /* address of linenumber table (offset in original rtnhdr) */
- int4 lnrtab_len; /* number of linenumber table entries */
- unsigned char *literal_text_adr; /* address of literal text pool (offset in original rtnhdr) */
- int4 literal_text_len; /* length of literal text pool */
- mval *literal_adr; /* (#) address of literal mvals (offset in original rtnhdr) */
- int4 literal_len; /* number of literal mvals */
- lnk_tabent *linkage_adr; /* (#) address of linkage Psect (offset in original rtnhdr) */
- int4 linkage_len; /* number of linkage entries */
- int4 rel_table_off; /* offset to relocation table (not kept) */
- int4 sym_table_off; /* offset to symbol table (not kept) */
- unsigned char *shared_ptext_adr; /* If set, ptext_adr points to local copy, this points to old shared copy */
- unsigned char *ptext_adr; /* (#) address of start of instructions (offset in original rtnhdr) */
- unsigned char *ptext_end_adr; /* (#) address of end of instructions + 1 (offset in original rtnhdr) */
+ mident routine_name; /* External routine name */
+ var_tabent *vartab_adr; /* (#) Address of variable table (offset in original rtnhdr) */
+ int4 vartab_len; /* (#) Number of variable table entries */
+ lab_tabent *labtab_adr; /* Address of label table (offset in original rtnhdr) */
+ int4 labtab_len; /* Number of label table entries */
+ lnr_tabent *lnrtab_adr; /* Address of linenumber table (offset in original rtnhdr) */
+ int4 lnrtab_len; /* Number of linenumber table entries */
+ unsigned char *literal_text_adr; /* Address of literal text pool (offset in original rtnhdr) */
+ int4 literal_text_len; /* Length of literal text pool */
+ mval *literal_adr; /* (#) Address of literal mvals (offset in original rtnhdr) */
+ int4 literal_len; /* Number of literal mvals */
+ lnk_tabent *linkage_adr; /* (#) Address of linkage Psect (offset in original rtnhdr) */
+ int4 linkage_len; /* Number of linkage entries */
+ int4 rel_table_off; /* Offset to relocation table (not kept) */
+ int4 sym_table_off; /* Offset to symbol table (not kept) */
+ unsigned char *shared_ptext_adr; /* If shared routine (shared library or object), points to shared copy */
+ unsigned char *ptext_adr; /* (#) address of start of instructions (offset in original rtnhdr)
+ * If shared routine, points to shared copy unless breakpoints are active.
+ * In that case, points to private copy.
+ */
+ unsigned char *ptext_end_adr; /* (#) Address of end of instructions + 1 (offset in original rtnhdr) */
int4 checksum; /* 4-byte source code checksum (for platforms where MD5 is unavailable) */
int4 temp_mvals; /* (#) temp_mvals value of current module version */
int4 temp_size; /* (#) temp_size value of current module version */
- struct rhead_struct *current_rhead_adr; /* (#) address of routine header of current module version */
- struct rhead_struct *old_rhead_adr; /* (#) chain of replaced routine headers */
+ struct rhead_struct *current_rhead_adr; /* (#) Address of routine header of current module version */
+ struct rhead_struct *old_rhead_adr; /* (#) Chain of replaced routine headers */
# ifdef GTM_TRIGGER
void_ptr_t trigr_handle; /* Type is void to avoid needing gv_trigger.h for gv_trigger_t type addr */
+# else
+ void_ptr_t filler1;
# endif
unsigned char checksum_md5[16]; /* 16-byte MD5 checksum of routine source code */
- struct rhead_struct *active_rhead_adr; /* chain of active old versions, fully reserved for continued use */
- routine_source *source_code; /* source code used by $TEXT */
+ struct rhead_struct *active_rhead_adr; /* Chain of active old versions, fully reserved for continued use */
+ routine_source *source_code; /* Source code used by $TEXT */
+ void_ptr_t zhist; /* If shared object -> validation list/array (actual type is zro_hist *) */
+ unsigned char *lbltext_ptr; /* Label name text blob if shared object replaced */
+ uint4 shared_len; /* Length of mmaped segment (needed for munmap) */
+ uint4 routine_source_offset; /* Offset of M source within literal text pool */
+ IA64_ONLY(void_ptr_t filler2;) /* IA64 needs 16 byte alignment */
} rhdtyp;
/* Routine table entry */
@@ -116,10 +126,10 @@ typedef struct
rhdtyp *rt_adr; /* Pointer to its routine header */
} rtn_tabent;
-/* byte offset of the routine_name field in the routine headers of pre-V5 releases */
+/* Byte offset of the routine_name field in the routine headers of pre-V5 releases */
#define PRE_V5_RTNHDR_RTNOFF 24
-/* byte offset of the routine_name mstr (len,addr) in V50 and V51 - only used in Tru64/HPUX-HPPA */
+/* Byte offset of the routine_name mstr (len,addr) in V50 and V51 - only used in Tru64/HPUX-HPPA */
#if defined(__osf__) || defined(__hppa)
# define V50V51_RTNHDR_RTNMSTR_OFFSET 24
# ifdef __osf__
@@ -135,7 +145,7 @@ typedef struct
int4 *addr; /* Offset at this stage */
} v50v51_mstr;
#endif
-#
+
/* Macros for accessing routine header fields in a portable way */
#define VARTAB_ADR(rtnhdr) ((rtnhdr)->vartab_adr)
#define LABTAB_ADR(rtnhdr) ((rtnhdr)->labtab_adr)
@@ -188,8 +198,8 @@ struct rel_table
*/
struct nlist
{
- int4 n_type; /* type flag, i.e. N_TEXT etc; see below */
- uint4 n_value; /* value of this symbol (or sdb offset) */
+ int4 n_type; /* Type flag, i.e. N_TEXT etc; see below */
+ uint4 n_value; /* Value of this symbol (or sdb offset) */
};
struct sym_table
@@ -203,8 +213,8 @@ struct sym_table
};
/* Simple values for n_type. */
-#define N_TEXT 0x04 /* text */
-#define N_EXT 0x01 /* external bit, or'ed in */
+#define N_TEXT 0x04 /* Text */
+#define N_EXT 0x01 /* cexternal bit, or'ed in */
/* Flag values for get_src_line call */
#define VERIFY TRUE
@@ -226,5 +236,8 @@ rhdtyp *op_rhdaddr1(mval *name);
lnr_tabent **op_labaddr(rhdtyp *routine, mval *label, int4 offset);
void urx_resolve(rhdtyp *rtn, lab_tabent *lbl_tab, lab_tabent *lbl_top);
char *rtnlaboff2entryref(char *entryref_buff, mident *rtn, mident *lab, int offset);
+boolean_t on_stack(rhdtyp *rtnhdr, boolean_t *need_duplicate);
+rhdtyp *op_rhd_ext(mval *rtname, mval *lblname, rhdtyp *rhd, void *lnr);
+void *op_lab_ext(void);
#endif /* RTNHDR_H_INCLUDED */
diff --git a/sr_unix/rts_error.c b/sr_unix/rts_error.c
index cb2dfd7..891a311 100644
--- a/sr_unix/rts_error.c
+++ b/sr_unix/rts_error.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -63,7 +63,7 @@ int rts_error(int argcnt, ...)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- csa = (ANTICIPATORY_FREEZE_AVAILABLE && jnlpool.jnlpool_ctl) ? REG2CSA(gv_cur_region) : NULL;
+ csa = CUSTOM_ERRORS_LOADED ? REG2CSA(gv_cur_region) : NULL;
VAR_START(var, argcnt);
return rts_error_va(csa, argcnt, var);
}
@@ -80,7 +80,6 @@ int rts_error_va(void *csa, int argcnt, va_list var)
{
int msgid;
va_list var_dup;
- const err_msg *msg;
const err_ctl *ctl;
# ifdef DEBUG
DCL_THREADGBL_ACCESS;
@@ -109,21 +108,17 @@ int rts_error_va(void *csa, int argcnt, va_list var)
PRN_ERROR;
/* This is simply a place holder msg to signal tp restart or otherwise rethrow an error */
if ((ERR_TPRETRY == msgid) || (ERR_REPEATERROR == msgid) || (ERR_REPLONLNRLBK == msgid) || (ERR_JOBINTRRQST == msgid)
- || (ERR_JOBINTRRETHROW == msgid))
- error_condition = msgid;
- else
+ || (ERR_JOBINTRRETHROW == msgid))
+ {
+ SET_ERROR_CONDITION(msgid); /* sets "error_condition" & "severity" */
+ } else
{ /* Note this message is not flushed out. This is so user console is not polluted with messages that are going to be
* handled by a ZTRAP. If ZTRAP is not active, the message will be flushed out in mdb_condition_handler - which is
* usually the top level handler or is rolled over into by higher handlers.
*/
if (IS_GTMSECSHR_IMAGE)
util_out_print(NULL, RESET);
- if (NULL == (ctl = err_check(msgid)))
- msg = NULL;
- else
- GET_MSG_INFO(msgid, ctl, msg);
- error_condition = msgid;
- severity = NULL == msg ? ERROR : SEVMASK(msgid);
+ SET_ERROR_CONDITION(msgid); /* sets "error_condition" & "severity" */
gtm_putmsg_list(csa, argcnt, var);
if (DUMPABLE)
created_core = dont_want_core = FALSE; /* We can create a(nother) core now */
diff --git a/sr_unix/runall.csh b/sr_unix/runall.csh
index 739c998..712e2c1 100644
--- a/sr_unix/runall.csh
+++ b/sr_unix/runall.csh
@@ -1,7 +1,7 @@
#!/usr/local/bin/tcsh -f
#################################################################
# #
-# Copyright 2001, 2013 Fidelity Information Services, Inc #
+# Copyright 2001, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -161,9 +161,6 @@ lke lke
lke_cmd lke
geteuid geteuid
gtm mumps
-gtm_svc gtm_svc
-gtm_dal_svc gtm_svc
-gtm_rpc_init gtm_svc
gtmsecshr gtmsecshr
gtmsecshr_wrapper gtmsecshr
gtm_main mumps
@@ -491,11 +488,6 @@ if (! -z ${TMP_DIR}_src_files) then
set library=`grep " $file " ${TMP_DIR}_list | awk '{print $1}'`
if ("$library" == "") then
set library="libmumps.a"
- else
- set retain=`grep "^$file" $gtm_tools/retain_list.txt`
- if ("$retain" != "") then
- echo $objfile >> ${TMP_DIR}_lib_.libmumps.a
- endif
endif
echo $objfile >> ${TMP_DIR}_lib_.$library
else
@@ -518,20 +510,12 @@ if (! -z ${TMP_DIR}_src_files) then
(ls -1 ${TMP_DIR}_lib_.* > ${TMP_DIR}_Lib_list) >& /dev/null
- set retainlist = ""
foreach lib_ (`cat ${TMP_DIR}_Lib_list`)
set libext = $lib_:e
set library = $lib_:r
set library = $library:e
set library = $library.$libext
- # Note down if any files in retain_list.txt are being compiled. If so we need to make sure we dont remove
- # those .o files after including them in libgtmrpc.a as they also needed to be included in libmumps.a
- if ("libgtmrpc.a" != $library) then
- set dstlib = "$gtm_obj/$library"
- else
- set dstlib = "$gtm_exe/$library"
- set retainlist = `cat $lib_ | egrep -f $gtm_tools/retain_list.txt`
- endif
+ set dstlib = "$gtm_obj/$library"
# remove pre-existing object files from object library to ensure an older working version of the module does
# not get used in case the current version of the module did not compile and failed to produce an object file.
gt_ar $gt_ar_option_delete $dstlib `cat $lib_` >& /dev/null
@@ -543,11 +527,7 @@ if (! -z ${TMP_DIR}_src_files) then
if (0 != $status) @ runall_status = $status
endif
if (0 != $status) @ runall_status = $status
- if (("" != "$retainlist") && ("libgtmrpc.a" == $library)) then
- rm -f `cat $lib_ | egrep -v -f $gtm_tools/retain_list.txt`
- else
- rm -f `cat $lib_`
- endif
+ cat $lib_ | xargs rm -f
echo ""
end
if (0 != $runall_status) then
diff --git a/sr_unix/secshr_client.c b/sr_unix/secshr_client.c
index c7eddba..516f1e0 100644
--- a/sr_unix/secshr_client.c
+++ b/sr_unix/secshr_client.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -34,6 +34,7 @@
#include "gtmio.h"
#include "io.h"
#include "gtmsecshr.h"
+#include "gtmimagename.h"
#include "iosp.h"
#include "error.h"
#include "eintr_wrappers.h"
@@ -65,9 +66,11 @@ GBLREF boolean_t gtmsecshr_sock_init_done;
GBLREF uint4 process_id;
GBLREF ipcs_mesg db_ipcs;
GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
LITREF char gtm_release_name[];
LITREF int4 gtm_release_name_len;
+LITREF gtmImageName gtmImageNames[];
static int secshr_sem;
static boolean_t gtmsecshr_file_check_done;
@@ -139,6 +142,7 @@ const static char readonly *secshrstart_error_code[] = {
start_timer(timer_id, msec_timeout, client_timer_handler, 0, NULL); \
}
+error_def(ERR_GTMDISTUNVERIF);
error_def(ERR_GTMSECSHR);
error_def(ERR_GTMSECSHRPERM);
error_def(ERR_GTMSECSHRSOCKET);
@@ -184,6 +188,9 @@ int send_mesg2gtmsecshr(unsigned int code, unsigned int id, char *path, int path
SETUP_THREADGBL_ACCESS;
DBGGSSHR((LOGFLAGS, "secshr_client: New send request\n"));
+ if (!gtm_dist_ok_to_use)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, STRLEN(gtm_dist), gtm_dist,
+ gtmImageNames[image_type].imageNameLen, gtmImageNames[image_type].imageName);
/* Create communication key (hash of release name) if it has not already been done */
if (0 == TREF(gtmsecshr_comkey))
{
@@ -193,23 +200,12 @@ int send_mesg2gtmsecshr(unsigned int code, unsigned int id, char *path, int path
if (!gtmsecshr_file_check_done)
{
len = STRLEN(gtm_dist);
- if (!len)
- {
- send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_GTMSECSHRSTART, 3,
- RTS_ERROR_TEXT("Client"), process_id, ERR_TEXT, 2,
- RTS_ERROR_STRING(secshrstart_error_code[INVTRANSGTMSECSHR]));
- rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_GTMSECSHRSTART, 3,
- RTS_ERROR_TEXT("Client"), process_id, ERR_TEXT, 2,
- RTS_ERROR_STRING(secshrstart_error_code[INVTRANSGTMSECSHR]));
- }
memcpy(gtmsecshr_path, gtm_dist, len);
gtmsecshr_path[len] = '/';
memcpy(gtmsecshr_path + len + 1, GTMSECSHR_EXECUTABLE, STRLEN(GTMSECSHR_EXECUTABLE));
gtmsecshr_pathname.addr = gtmsecshr_path;
gtmsecshr_pathname.len = len + 1 + STRLEN(GTMSECSHR_EXECUTABLE);
- if (GTM_PATH_MAX <= gtmsecshr_pathname.len)
- send_msg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_TEXT, 2,
- RTS_ERROR_LITERAL("gtmsecshr path too long"));
+ assertpro(GTM_PATH_MAX > gtmsecshr_pathname.len);
gtmsecshr_pathname.addr[gtmsecshr_pathname.len] = '\0';
if (-1 == Stat(gtmsecshr_pathname.addr, &stat_buf))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
@@ -441,7 +437,7 @@ int create_server(void)
# endif
int save_errno;
- FORK(child_pid); /* BYPASSOK: we exec immediately, no FORK_CLEAN needed */
+ FORK(child_pid);
if (0 == child_pid)
{
process_id = getpid();
diff --git a/sr_unix/send_msg.c b/sr_unix/send_msg.c
index c8c67ea..d278d4f 100644
--- a/sr_unix/send_msg.c
+++ b/sr_unix/send_msg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -59,7 +59,7 @@ void send_msg(int arg_count, ...)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- csa = (ANTICIPATORY_FREEZE_AVAILABLE && jnlpool.jnlpool_ctl) ? REG2CSA(gv_cur_region) : NULL;
+ csa = CUSTOM_ERRORS_LOADED ? REG2CSA(gv_cur_region) : NULL;
VAR_START(var, arg_count);
send_msg_va(csa, arg_count, var);
va_end(var);
diff --git a/sr_unix/source_file.c b/sr_unix/source_file.c
index 0540f27..58a2d0f 100644
--- a/sr_unix/source_file.c
+++ b/sr_unix/source_file.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,6 +33,7 @@
#include "min_max.h"
#include "cli.h"
#include "have_crit.h"
+#include "op_fnzsearch.h"
GBLREF unsigned short source_name_len;
GBLREF unsigned char source_file_name[];
@@ -46,6 +47,8 @@ GBLREF short object_name_len;
GBLREF int object_file_des;
GBLREF command_qualifier cmd_qlf;
+LITREF mval literal_null;
+
static bool tt_so_do_once;
static io_pair compile_src_dev;
static io_pair dev_in_use; /* before opening source file */
@@ -92,9 +95,10 @@ void compile_source_file(unsigned short flen, char *faddr, boolean_t MFtIsReqd)
fstr.str.len = flen;
ESTABLISH(source_ch);
tt_so_do_once = FALSE;
+ op_fnzsearch((mval *)&literal_null, STRM_COMP_SRC, 0, &ret); /* Clear any remaining stream cache */
for (i = 0 ; ; i++)
{
- plen.p.pint = op_fnzsearch(&fstr, 0, &ret);
+ plen.p.pint = op_fnzsearch(&fstr, STRM_COMP_SRC, 0, &ret);
if (!ret.str.len)
{
if (!i)
diff --git a/sr_unix/ss_initiate.c b/sr_unix/ss_initiate.c
index 0194fa6..8e4341b 100644
--- a/sr_unix/ss_initiate.c
+++ b/sr_unix/ss_initiate.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2009, 2013 Fidelity Information Services, Inc *
+ * Copyright 2009, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -62,18 +62,16 @@
#include "ss_lock_facility.h"
#include "gtmimagename.h"
-GBLREF uint4 process_id;
-GBLREF uint4 mu_int_errknt;
-GBLREF boolean_t ointeg_this_reg;
-GBLREF boolean_t online_specified;
+GBLREF boolean_t muint_fast, ointeg_this_reg, online_specified;
GBLREF gd_region *gv_cur_region;
+GBLREF uint4 process_id;
GBLREF void (*call_on_signal)();
+#ifdef DEBUG_ONLY
GBLREF int process_exiting;
-GBLREF boolean_t muint_fast;
+#endif
error_def(ERR_BUFFLUFAILED);
error_def(ERR_DBROLLEDBACK);
-error_def(ERR_FILEPARSE);
error_def(ERR_MAXSSREACHED);
error_def(ERR_PERMGENFAIL);
error_def(ERR_SSFILOPERR);
@@ -199,30 +197,32 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
boolean_t preserve_snapshot, /* Should the snapshots be preserved ? */
char *calling_utility) /* Who called ss_initiate */
{
+ boolean_t debug_mupip = FALSE;
+ boolean_t final_retry, wait_for_zero_kip;
+ char *tempfilename, eof_marker[EOF_MARKER_SIZE], tempdir_trans_buffer[GTM_PATH_MAX];
+ char tempdir_full_buffer[GTM_PATH_MAX], tempnamprefix[MAX_FN_LEN + 1];
+ char *time_ptr, time_str[CTIME_BEFORE_NL + 2]; /* for GET_CUR_TIME macro */
+ enum db_acc_method acc_meth;
+ gtm_uint64_t db_file_size, native_size;
+ DEBUG_ONLY(gtm_uint64_t db_size;)
+ int dsk_addr = 0;
+ int fclose_res, fstat_res, group_id, perm, pwrite_res, retries;
+ int save_errno, shdw_fd, ss_shmsize, ss_shm_vbn, status, tmpfd, user_id;
+ ZOS_ONLY(int realfiletag;)
+ long ss_shmid = INVALID_SHMID;
+ mstr tempdir_full, tempdir_log, tempdir_trans;
+ now_t now;
+ pid_t *kip_pids_arr_ptr;
sgmnt_addrs *csa;
sgmnt_data_ptr_t csd;
node_local_ptr_t cnl;
shm_snapshot_ptr_t ss_shm_ptr;
- snapshot_context_ptr_t lcl_ss_ctx, ss_orphan_ctx;
+ snapshot_context_ptr_t lcl_ss_ctx;
snapshot_filhdr_ptr_t ss_filhdr_ptr;
- int shdw_fd, tmpfd, fclose_res, fstat_res, status, perm, user_id, group_id, pwrite_res, dsk_addr = 0;
- int retries, idx, this_snapshot_idx, save_errno, ss_shmsize, ss_shm_vbn;
- ZOS_ONLY(int realfiletag;)
- long ss_shmid = INVALID_SHMID;
- char tempnamprefix[MAX_FN_LEN + 1], tempdir_full_buffer[GTM_PATH_MAX], *tempfilename;
- char tempdir_trans_buffer[GTM_PATH_MAX], eof_marker[EOF_MARKER_SIZE];
- char *time_ptr, time_str[CTIME_BEFORE_NL + 2]; /* for GET_CUR_TIME macro */
+ struct perm_diag_data pdd;
struct stat stat_buf;
- enum db_acc_method acc_meth;
+ uint4 crit_counter, fstat_status, prev_ss_shmsize, tempnamprefix_len, tot_blks;
void *ss_shmaddr;
- gtm_uint64_t db_file_size, native_size;
- DEBUG_ONLY(gtm_uint64_t db_size;)
- uint4 tempnamprefix_len, crit_counter, tot_blks, prev_ss_shmsize, fstat_status;
- pid_t *kip_pids_arr_ptr;
- mstr tempdir_log, tempdir_full, tempdir_trans;
- boolean_t debug_mupip = FALSE, wait_for_zero_kip, final_retry;
- now_t now;
- struct perm_diag_data pdd;
assert(IS_MUPIP_IMAGE);
assert(NULL != calling_utility);
@@ -231,7 +231,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
cnl = csa->nl;
acc_meth = csd->acc_meth;
debug_mupip = (CLI_PRESENT == cli_present("DBG"));
-
/* Create a context containing default information pertinent to this initiate invocation */
lcl_ss_ctx = malloc(SIZEOF(snapshot_context_t)); /* should be free'd by ss_release */
DEFAULT_INIT_SS_CTX(lcl_ss_ctx);
@@ -266,7 +265,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
cnl->num_snapshots_in_effect++;
assert(ss_lock_held_by_us(reg));
ss_release_lock(reg);
-
/* For a readonly database for the current process, we better have the region frozen */
assert(!reg->read_only || csd->freeze);
/* ============================ STEP 1 : Shadow file name construction ==============================
@@ -282,7 +280,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
* borrowed from mupip_backup.c. This code should be modularized and should be used in both mupip_backup
* as well as here.
*/
-
/* set up a prefix for the temporary file. */
tempnamprefix_len = 0;
memset(tempnamprefix, 0, MAX_FN_LEN);
@@ -291,7 +288,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
memcpy(tempnamprefix + tempnamprefix_len, reg->rname, reg->rname_len);
tempnamprefix_len += reg->rname_len;
SNPRINTF(&tempnamprefix[tempnamprefix_len], MAX_FN_LEN, "_%x", process_id);
-
tempdir_log.addr = GTM_SNAPTMPDIR;
tempdir_log.len = STR_LIT_LEN(GTM_SNAPTMPDIR);
tempfilename = tempdir_full.addr = tempdir_full_buffer;
@@ -304,7 +300,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
tempdir_trans_buffer,
SIZEOF(tempdir_trans_buffer),
do_sendmsg_on_log2long);
-
if (SS_NORMAL == status && (NULL != tempdir_trans.addr) && (0 != tempdir_trans.len))
*(tempdir_trans.addr + tempdir_trans.len) = 0;
else
@@ -325,7 +320,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
tempdir_trans.len = 1;
}
}
-
/* Verify if we can stat the temporary directory */
if (FILE_STAT_ERROR == (fstat_res = gtm_file_stat(&tempdir_trans, NULL, &tempdir_full, FALSE, &fstat_status)))
{
@@ -334,7 +328,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
return FALSE;
}
SNPRINTF(tempfilename + tempdir_full.len, GTM_PATH_MAX, "/%s_XXXXXX", tempnamprefix);
-
/* ========================== STEP 2 : Create the shadow file ======================== */
/* get a unique temporary file name. The file gets created on success */
DEFER_INTERRUPTS(INTRPT_IN_SS_INITIATE); /* Defer MUPIP STOP till the file is created */
@@ -349,6 +342,7 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
status = errno;
gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_SSTMPCREATE, 2, tempdir_trans.len, tempdir_trans.addr, status);
UNFREEZE_REGION_IF_NEEDED(csd, reg);
+ ENABLE_INTERRUPTS(INTRPT_IN_SS_INITIATE);
return FALSE;
}
# ifdef __MVS__
@@ -368,6 +362,7 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_SSFILOPERR, 4, LEN_AND_LIT("open"),
tempdir_full.len, tempdir_full.addr, status);
UNFREEZE_REGION_IF_NEEDED(csd, reg);
+ ENABLE_INTERRUPTS(INTRPT_IN_SS_INITIATE);
return FALSE;
}
# ifdef __MVS__
@@ -380,7 +375,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
ENABLE_INTERRUPTS(INTRPT_IN_SS_INITIATE);
tempdir_full.len = STRLEN(tempdir_full.addr); /* update the length */
assert(GTM_PATH_MAX >= tempdir_full.len);
-
/* give temporary files the group and permissions as other shared resources - like journal files */
FSTAT_FILE(((unix_db_info *)(reg->dyn.addr->file_cntl->file_info))->fd, &stat_buf, fstat_res);
assert(-1 != fstat_res);
@@ -419,7 +413,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
tempdir_full.len,
tempdir_full.addr);
}
-
/* STEP 3: Wait for kills-in-progress and initialize snapshot shadow file
*
* Snapshot Shadow File Layout -
@@ -491,6 +484,7 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
{ /* error while creating shared memory */
GET_CRIT_AND_DECR_INHIBIT_KILLS(reg, cnl);
UNFREEZE_REGION_IF_NEEDED(csd, reg);
+ ENABLE_INTERRUPTS(INTRPT_IN_SS_INITIATE);
return FALSE;
}
/* At this point, we are done with allocating shared memory (aligned with OS_PAGE_SIZE) enough to hold
@@ -633,7 +627,6 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
}
}
/* ===================== STEP 5: Flush the pending updates in the global cache =================== */
-
/* For a readonly database for the current process, we cannot do wcs_flu. We would have waited for the active queues
* to complete in mu_int_reg after doing a freeze. Now that we have crit, unfreeze the region
*/
@@ -652,11 +645,9 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
assert(0 < cnl->num_snapshots_in_effect || (!SNAPSHOTS_IN_PROG(cnl)));
assert(csa->now_crit);
/* ========== STEP 6: Copy the file header, master map and the native file size into a private structure =========== */
-
memcpy(util_ss_ptr->header, csd, SGMNT_HDR_LEN);
memcpy(util_ss_ptr->master_map, MM_ADDR(csd), MASTER_MAP_SIZE(csd));
util_ss_ptr->native_size = native_size;
-
/* We are about to copy the process private variables to shared memory. Although we have done grab_crit above, we take
* snapshot crit lock to ensure that no other process attempts snapshot cleanup.
*/
@@ -706,6 +697,7 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
*/
gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(1) ERR_DBROLLEDBACK);
UNFREEZE_REGION_IF_NEEDED(csa, reg);
+ ENABLE_INTERRUPTS(INTRPT_IN_SS_INITIATE);
return FALSE;
}
/* ============= STEP 8: Write the database file header and the master map =============
@@ -714,13 +706,19 @@ boolean_t ss_initiate(gd_region *reg, /* Region in which snapshot has to be s
* shared memory information at the beginning of the file. */
LSEEKWRITE(shdw_fd, (off_t)ss_shmsize, (sm_uc_ptr_t)util_ss_ptr->header, SGMNT_HDR_LEN, pwrite_res);
if (0 != pwrite_res)
+ {
+ ENABLE_INTERRUPTS(INTRPT_IN_SS_INITIATE);
ISSUE_WRITE_ERROR_AND_EXIT(reg, pwrite_res, csa, tempfilename);
+ }
dsk_addr += ((int)ss_shmsize + (int)SGMNT_HDR_LEN);
/* write the database master map to the shadow file */
assert(0 == ((dsk_addr + MASTER_MAP_SIZE_MAX) % OS_PAGE_SIZE));
LSEEKWRITE(shdw_fd, dsk_addr, (sm_uc_ptr_t)util_ss_ptr->master_map, MASTER_MAP_SIZE(csd), pwrite_res);
if (0 != pwrite_res)
+ {
+ ENABLE_INTERRUPTS(INTRPT_IN_SS_INITIATE);
ISSUE_WRITE_ERROR_AND_EXIT(reg, pwrite_res, csa, tempfilename);
+ }
/* The size of the master map written to snap-shot file is read from database header i.e. MASTER_MAP_SIZE(csd).
* That is the actual size which may differ depending on the version that created the database file.
* But this sets the dsk_addr for the Starting VBN using the current MASTER_MAP_SIZE_MAX to keep it aligned
diff --git a/sr_unix/std_dev_outbndset.c b/sr_unix/std_dev_outbndset.c
index 596a207..17d8904 100644
--- a/sr_unix/std_dev_outbndset.c
+++ b/sr_unix/std_dev_outbndset.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,8 +18,9 @@
#define SHFT_MSK 0x00000001
-GBLREF volatile io_pair io_std_device;
-GBLREF volatile int4 spc_inp_prc;
+GBLREF boolean_t ctrlc_on;
+GBLREF volatile io_pair io_std_device;
+GBLREF volatile int4 spc_inp_prc;
GBLREF volatile bool ctrlu_occurred;
GBLREF volatile bool std_dev_outbnd;
@@ -30,13 +31,12 @@ GBLREF volatile bool std_dev_outbnd;
void std_dev_outbndset(int4 ob_char)
{
- uint4 mask;
- unsigned short n;
- d_tt_struct *tt_ptr;
+ uint4 mask;
+ unsigned short n;
+ d_tt_struct *tt_ptr;
- if (MAXOUTOFBAND < ob_char)
- GTMASSERT;
- else if (tt == io_std_device.in->type)
+ assertpro(MAXOUTOFBAND >= ob_char);
+ if (tt == io_std_device.in->type)
{
tt_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
std_dev_outbnd = TRUE;
@@ -44,12 +44,15 @@ void std_dev_outbndset(int4 ob_char)
if (mask & tt_ptr->enbld_outofbands.mask)
(void)xfer_set_handlers(outofband_event, &ctrap_set, ob_char);
else if (mask & CTRLC_MSK)
- (void)xfer_set_handlers(outofband_event, &ctrlc_set, 0);
- else if (mask & CTRLY_MSK)
+ {
+ if (ctrlc_on)
+ (void)xfer_set_handlers(outofband_event, &ctrlc_set, 0);
+ } else if (mask & CTRLY_MSK)
(void)xfer_set_handlers(outofband_event, &ctrly_set, 0);
else if ((CTRL_U == ob_char) && (spc_inp_prc & (SHFT_MSK << CTRL_U)))
ctrlu_occurred = TRUE;
else
- GTMASSERT;
+ assertpro((mask & tt_ptr->enbld_outofbands.mask) || (mask & CTRLC_MSK) || (mask & CTRLY_MSK)
+ || ((CTRL_U == ob_char) && (spc_inp_prc & (SHFT_MSK << CTRL_U))));
}
}
diff --git a/sr_unix/term_setup.c b/sr_unix/term_setup.c
index 426aa13..05bba13 100644
--- a/sr_unix/term_setup.c
+++ b/sr_unix/term_setup.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,12 +13,12 @@
#include "io.h"
#include "term_setup.h"
+GBLDEF boolean_t ctrlc_on; /* TRUE in cenable mode; FALSE in nocenable mode */
+
GBLREF int4 outofband; /*enumerated:ctrap,ctrlc or ctrly*/
GBLREF io_pair io_std_device; /* standard device */
-GBLDEF bool ctrlc_on; /* whether ctrlc trap enabled*/
-
-void term_setup(bool ctrlc_enable)
+void term_setup(boolean_t ctrlc_enable)
{
outofband = 0;
ctrlc_on = (io_std_device.in->type == tt) ? ctrlc_enable : FALSE;
diff --git a/sr_unix/trigger_delete.c b/sr_unix/trigger_delete.c
index 63fa7c4..5ce31ba 100644
--- a/sr_unix/trigger_delete.c
+++ b/sr_unix/trigger_delete.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -46,25 +46,30 @@
#include "util.h"
#include "zshow.h" /* for format2zwr() prototype */
#include "hashtab_mname.h"
+#include "t_begin.h"
+#include "repl_msg.h"
+#include "gtmsource.h"
+GBLREF boolean_t dollar_ztrigger_invoked;
+GBLREF gd_addr *gd_header;
GBLREF gd_region *gv_cur_region;
-GBLREF sgm_info *sgm_info_ptr;
GBLREF gv_key *gv_currkey;
-GBLREF gd_addr *gd_header;
-GBLREF sgmnt_data_ptr_t cs_data;
GBLREF gv_namehead *gv_target;
-GBLREF boolean_t dollar_ztrigger_invoked;
GBLREF gv_namehead *gv_target_list;
+GBLREF sgm_info *sgm_info_ptr;
+GBLREF sgmnt_data_ptr_t cs_data;
GBLREF trans_num local_tn;
+GBLREF uint4 dollar_tlevel;
LITREF mval literal_hasht;
LITREF char *trigger_subs[];
error_def(ERR_TEXT);
error_def(ERR_TRIGDEFBAD);
+error_def(ERR_TRIGLOADFAIL);
error_def(ERR_TRIGMODINTP);
-error_def(ERR_TRIGNAMBAD);
error_def(ERR_TRIGMODREGNOTRW);
+error_def(ERR_TRIGNAMBAD);
#define MAX_CMD_LEN 20 /* Plenty of room for S,K,ZK,ZTK */
@@ -338,7 +343,6 @@ boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4
char curr_name[MAX_MIDENT_LEN + 1];
uint4 curr_name_len, orig_name_len;
mname_entry gvname;
- int len;
mval mv_curr_nam;
boolean_t name_found;
char *ptr;
@@ -357,10 +361,15 @@ boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4
int badpos;
boolean_t wildcard;
gvnh_reg_t *gvnh_reg;
+ mval trigjrec;
+ boolean_t jnl_format_done;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
badpos = 0;
+ trigjrec.mvtype = MV_STR;
+ trigjrec.str.len = trigger_name_len--;
+ trigjrec.str.addr = trigger_name++;
orig_name_len = trigger_name_len;
if ((0 == trigger_name_len) || (trigger_name_len !=
(badpos = validate_input_trigger_name(trigger_name, trigger_name_len, &wildcard))))
@@ -381,7 +390,25 @@ boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4
if (0 == gv_target->root)
{
util_out_print_gtmio("Trigger named !AD does not exist", FLUSH, orig_name_len, trigger_name);
- return TRIG_FAILURE;
+ trig_stats[STATS_UNCHANGED]++;
+ return TRIG_SUCCESS;
+ }
+ /* To write the LGTRIG logical jnl record, choose the first region that has journaling enabled */
+ jnl_format_done = FALSE;
+ csa = cs_addrs;
+ if (JNL_WRITE_LOGICAL_RECS(csa))
+ {
+ assert(!gv_cur_region->read_only);
+ /* Attach to jnlpool. Normally SET or KILL of the ^#t records take care of this but in case this is a NO-OP
+ * trigger operation that wont happen and we still want to write a TLGTRIG/ULGTRIG journal record. Hence
+ * the need to do this.
+ */
+ JNLPOOL_INIT_IF_NEEDED(csa, csa->hdr, csa->nl);
+ assert(dollar_tlevel);
+ T_BEGIN_SETORKILL_NONTP_OR_TP(ERR_TRIGLOADFAIL); /* needed to set update_trans TRUE on this region
+ * even if NO db updates happen to ^#t nodes. */
+ jnl_format(JNL_LGTRIG, NULL, &trigjrec, 0);
+ jnl_format_done = TRUE;
}
name_found = FALSE;
assert(trigger_name_len < MAX_MIDENT_LEN);
@@ -411,11 +438,21 @@ boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4
csa = cs_addrs;
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_TRIGMODREGNOTRW, 2, REG_LEN_STR(gv_cur_region));
+ /* To write the LGTRIG logical jnl record, choose the first region that has journaling enabled */
+ if (!jnl_format_done && JNL_WRITE_LOGICAL_RECS(csa))
+ {
+ assert(!gv_cur_region->read_only);
+ JNLPOOL_INIT_IF_NEEDED(csa, csa->hdr, csa->nl); /* see previous usage for why it is needed */
+ assert(dollar_tlevel);
+ T_BEGIN_SETORKILL_NONTP_OR_TP(ERR_TRIGLOADFAIL); /* needed to set update_trans TRUE on this region
+ * even if NO db updates happen to ^#t nodes. */
+ jnl_format(JNL_LGTRIG, NULL, &trigjrec, 0);
+ jnl_format_done = TRUE;
+ }
SET_GVTARGET_TO_HASHT_GBL(csa);
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
/* $get(^#t(GVN,"COUNT") */
BUILD_HASHT_SUB_SUB_CURRKEY(trigvn, trigvn_len, LITERAL_HASHCOUNT, STRLEN(LITERAL_HASHCOUNT));
- /* if it does not exist, return false */
if (!gvcst_get(&trigger_count))
{
util_out_print_gtmio("Trigger named !AD exists in the lookup table, "
@@ -446,14 +483,6 @@ boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4
}
RESTORE_TRIGGER_REGION_INFO(save_currkey);
name_found = TRUE;
- } else
- { /* no names match, if !wildcard report an error */
- if (!wildcard)
- {
- util_out_print_gtmio("Trigger named !AD does not exist",
- FLUSH, orig_name_len, trigger_name);
- return TRIG_FAILURE;
- }
}
if (!wildcard)
/* not a wild card, don't $order for the next match */
@@ -468,10 +497,18 @@ boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4
/* stop when gv_order returns a string that no longer starts save_name */
break;
} while (wildcard);
- if (name_found)
+ if (!name_found)
+ {
+ util_out_print_gtmio("Trigger named !AD does not exist", FLUSH, orig_name_len, trigger_name);
+ if (wildcard)
+ return TRIG_FAILURE;
+ else
+ {
+ trig_stats[STATS_UNCHANGED]++;
+ return TRIG_SUCCESS;
+ }
+ } else
return TRIG_SUCCESS;
- util_out_print_gtmio("Trigger named !AD does not exist", FLUSH, orig_name_len, trigger_name);
- return TRIG_FAILURE;
}
int4 trigger_delete(char *trigvn, int trigvn_len, mval *trigger_count, int index)
@@ -684,7 +721,7 @@ int4 trigger_delete(char *trigvn, int trigvn_len, mval *trigger_count, int index
return PUT_SUCCESS;
}
-void trigger_delete_all(void)
+void trigger_delete_all(char *trigger_rec, uint4 len)
{
int count;
char count_str[MAX_DIGITS_IN_INT + 1];
@@ -705,6 +742,8 @@ void trigger_delete_all(void)
mval trigger_cycle;
mval trigger_count;
mval val;
+ mval trigjrec;
+ boolean_t jnl_format_done;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -722,14 +761,31 @@ void trigger_delete_all(void)
if (gv_cur_region->read_only)
rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_TRIGMODREGNOTRW, 2, REG_LEN_STR(gv_cur_region));
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
+ jnl_format_done = FALSE;
+ trigjrec.mvtype = MV_STR;
+ trigjrec.str.len = len;
+ trigjrec.str.addr = trigger_rec;
if (0 != gv_target->root)
{
+ csa = cs_addrs;
+ /* To write the LGTRIG logical jnl record, choose the first region that has journaling enabled */
+ if (!jnl_format_done && JNL_WRITE_LOGICAL_RECS(csa))
+ {
+ JNLPOOL_INIT_IF_NEEDED(csa, csa->hdr, csa->nl); /* see previous usage for comment on why it is needed */
+ assert(dollar_tlevel);
+ T_BEGIN_SETORKILL_NONTP_OR_TP(ERR_TRIGLOADFAIL); /* needed to set update_trans TRUE on this region
+ * even if NO db updates happen to ^#t nodes. */
+ jnl_format(JNL_LGTRIG, NULL, &trigjrec, 0);
+ jnl_format_done = TRUE;
+ }
/* kill ^#t("#TRHASH") */
BUILD_HASHT_SUB_CURRKEY(LITERAL_HASHTRHASH, STRLEN(LITERAL_HASHTRHASH));
- gvcst_kill(TRUE);
+ if (0 != gvcst_data())
+ gvcst_kill(TRUE);
/* kill ^#t("#TNAME") */
BUILD_HASHT_SUB_CURRKEY(LITERAL_HASHTNAME, STRLEN(LITERAL_HASHTNAME));
- gvcst_kill(TRUE);
+ if (0 != gvcst_data())
+ gvcst_kill(TRUE);
}
for (reg_indx = 0, reg = gd_header->regions; reg_indx < gd_header->n_regions; reg_indx++, reg++)
{
@@ -738,6 +794,16 @@ void trigger_delete_all(void)
gv_cur_region = reg;
change_reg();
csa = cs_addrs;
+ /* To write the LGTRIG logical jnl record, choose the first region that has journaling enabled */
+ if (!reg->read_only && !jnl_format_done && JNL_WRITE_LOGICAL_RECS(csa))
+ {
+ JNLPOOL_INIT_IF_NEEDED(csa, csa->hdr, csa->nl); /* see previous usage for comment on why it is needed */
+ assert(dollar_tlevel);
+ T_BEGIN_SETORKILL_NONTP_OR_TP(ERR_TRIGLOADFAIL); /* needed to set update_trans TRUE on this region
+ * even if NO db updates happen to ^#t nodes. */
+ jnl_format(JNL_LGTRIG, NULL, &trigjrec, 0);
+ jnl_format_done = TRUE;
+ }
SET_GVTARGET_TO_HASHT_GBL(csa);
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
/* There might not be any ^#t in this region, so check */
diff --git a/sr_unix/trigger_delete_protos.h b/sr_unix/trigger_delete_protos.h
index 442f6ab..61c7934 100644
--- a/sr_unix/trigger_delete_protos.h
+++ b/sr_unix/trigger_delete_protos.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,6 +21,6 @@ STATICFNDCL int4 update_trigger_name_value(int trigvn_len, char *trig_name, int
boolean_t trigger_delete_name(char *trigger_name, uint4 trigger_name_len, uint4 *trig_stats);
int4 trigger_delete(char *trigvn, int trigvn_len, mval *trigger_count, int index);
-void trigger_delete_all(void);
+void trigger_delete_all(char *trigger_rec, uint4 len);
#endif
diff --git a/sr_unix/trigger_parse.c b/sr_unix/trigger_parse.c
index 18ac7c7..e5be210 100644
--- a/sr_unix/trigger_parse.c
+++ b/sr_unix/trigger_parse.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2012 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -298,7 +298,7 @@ STATICFNDEF boolean_t process_dollar_char(char **src_ptr, int *src_len, boolean_
len = *src_len;
lcl_dst_len = *dst_len;
assert('$' == *ptr);
- UPDATE_DST(ptr, len, have_star, dst_ptr, lcl_dst_len, MAX_GVSUBS_LEN);
+ UPDATE_DST(ptr, len, have_star, dst_ptr, lcl_dst_len, MAX_GVSUBS_LEN);
if (0 == len)
return FALSE;
switch (*ptr)
@@ -592,7 +592,7 @@ STATICFNDEF boolean_t process_options(char *option_str, uint4 option_len, boolea
}
break;
default:
- GTMASSERT; /* Parsing should have found invalid command */
+ assertpro(FALSE); /* Parsing should have found invalid command */
break;
}
} while (ptr = strtok(NULL, ","));
@@ -789,7 +789,7 @@ STATICFNDEF boolean_t process_subscripts(char *subscr_str, uint4 *subscr_len, ch
util_out_print_gtmio("Invalid pattern match range", FLUSH);
return FALSE;
}
- switch (toupper(*ptr))
+ switch (TOUPPER(*ptr))
{
case 'E':
if (have_dot && (0 >= num1) && (-1 == num2))
@@ -1413,10 +1413,10 @@ boolean_t trigger_parse(char *input, uint4 input_len, char *trigvn, char **value
GET_CLI_STR_AND_CHECK("ZDELIM", zdelim_present, max_output_len, process_delim, values[ZDELIM_SUB], value_len[ZDELIM_SUB],
values[XECUTE_SUB], "Error parsing ZDELIM string: ");
/* Since process_xecute() does a test compile of the xecute string, it changes the parsing table from MUPIP TRIGGER
- * to GT.M. To avoid problems with saving and restoring the parse state (which would have to be done with globals
- * that are static in cli_parse.c), it is much easier to put process_xecute() last in the list of qualifiers to check -
- * solving the problem. In other words, don't try to neaten things up by making the qualifiers alphabetical!
- */
+ * to GT.M. To avoid problems with saving and restoring the parse state (which would have to be done with globals
+ * that are static in cli_parse.c), it is much easier to put process_xecute() last in the list of qualifiers to check -
+ * solving the problem. In other words, don't try to neaten things up by making the qualifiers alphabetical!
+ */
if (CLI_PRESENT == (xecute_present = cli_present("XECUTE")))
{
GET_CLI_STR("XECUTE", max_output_len, values[XECUTE_SUB], value_len[XECUTE_SUB]);
@@ -1462,7 +1462,6 @@ boolean_t trigger_parse(char *input, uint4 input_len, char *trigvn, char **value
ERROR_STR_RETURN("Entry too large to properly index");
}
}
-
*multi_line_xecute = out_multi_line_xecute;
*max_len = max_output_len;
return TRIG_SUCCESS;
diff --git a/sr_unix/trigger_select.c b/sr_unix/trigger_select.c
index 4508ba8..43e6313 100644
--- a/sr_unix/trigger_select.c
+++ b/sr_unix/trigger_select.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -200,7 +200,7 @@ STATICFNDEF void write_out_trigger(char *gbl_name, uint4 gbl_name_len, uint4 fil
mval data_val;
char out_rec[MAX_BUFF_SIZE];
char *out_rec_ptr;
- char *ptr1, *ptr2;
+ char *ptr1, *ptr2, *ptrtop;
mval mi, trigger_count, trigger_value;
mval *mv_trig_cnt_ptr;
boolean_t multi_line;
@@ -368,16 +368,20 @@ STATICFNDEF void write_out_trigger(char *gbl_name, uint4 gbl_name_len, uint4 fil
if (multi_line)
{
ptr1 = xecute_buff;
+ ptrtop = xecute_buff + xecute_len;
do
{
+ xecute_len = ptrtop - ptr1;
ptr2 = memchr(ptr1, '\n', xecute_len);
+ if (NULL == ptr2)
+ ptr2 = ptrtop; /* if last line is not terminated by newline, make it so */
out_rec_ptr = out_rec;
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, ptr1, UINTCAST(ptr2 - ptr1));
STR2MVAL((*op_val), out_rec, (unsigned int)(out_rec_ptr - out_rec));
op_write(op_val);
op_wteol(1);
ptr1 = ptr2 + 1;
- } while (ptr1 < (xecute_buff + xecute_len));
+ } while (ptr1 < ptrtop);
out_rec_ptr = out_rec;
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, XTENDED_STOP, XTENDED_STOP_LEN);
STR2MVAL((*op_val), out_rec, (unsigned int)(out_rec_ptr - out_rec));
diff --git a/sr_unix/trigger_source_read_andor_verify.c b/sr_unix/trigger_source_read_andor_verify.c
index e96ebb1..5afcf20 100644
--- a/sr_unix/trigger_source_read_andor_verify.c
+++ b/sr_unix/trigger_source_read_andor_verify.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2011, 2013 Fidelity Information Services, Inc *
+ * Copyright 2011, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -415,7 +415,7 @@ STATICFNDEF boolean_t trigger_source_raov_trigload(mstr *trigname, gv_trigger_t
/* Find region trigger name is in */
if (!trigger_read_name_entry(trigname, &val))
{ /* Trigger name not found - nothing we can do */
- if (!TREF(in_op_fntext))
+ if (!TREF(op_fntext_tlevel))
{
CLEAR_IMPLICIT_TP_BEFORE_ERROR;
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TRIGNAMENF, 2, trigname->len, trigname->addr);
diff --git a/sr_unix/trigger_update.c b/sr_unix/trigger_update.c
index 4ee82ab..e641752 100644
--- a/sr_unix/trigger_update.c
+++ b/sr_unix/trigger_update.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010, 2013 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -56,6 +56,10 @@
#include "t_retry.h"
#include "gtmimagename.h"
#include "hashtab_mname.h"
+#include "t_begin.h"
+#include "repl_msg.h"
+#include "gtmsource.h"
+#include "zshow.h"
GBLREF sgmnt_data_ptr_t cs_data;
GBLREF sgm_info *first_sgm_info;
@@ -80,6 +84,7 @@ error_def(ERR_TEXT);
error_def(ERR_TPRETRY);
error_def(ERR_TPRETRY);
error_def(ERR_TRIGDEFBAD);
+error_def(ERR_TRIGLOADFAIL);
error_def(ERR_TRIGMODINTP);
error_def(ERR_TRIGMODREGNOTRW);
error_def(ERR_TRIGNOSPANGBL);
@@ -428,7 +433,6 @@ STATICFNDEF boolean_t check_unique_trigger_name(char *trigvn, int trigvn_len, ch
RESTORE_TRIGGER_REGION_INFO(save_currkey);
return TRUE;
}
- assert((MAX_HASH_INDEX_LEN + 1 + MAX_DIGITS_IN_INT) > gv_cur_region->max_rec_size);
/* $get(^#t("#TNAME",trigger_name) */
BUILD_HASHT_SUB_SUB_CURRKEY(LITERAL_HASHTNAME, STRLEN(LITERAL_HASHTNAME), trigger_name, trigger_name_len);
status = !gvcst_get(&val);
@@ -1097,9 +1101,12 @@ boolean_t trigger_update_rec(char *trigger_rec, uint4 len, boolean_t noprompt, u
uint4 value_len[NUM_SUBS];
stringkey kill_trigger_hash, set_trigger_hash;
char tmp_str[MAX_HASH_INDEX_LEN + 1 + MAX_DIGITS_IN_INT];
- char xecute_buffer[MAX_XECUTE_LEN];
+ char xecute_buffer[MAX_BUFF_SIZE + MAX_XECUTE_LEN];
mval xecute_index, xecute_size;
mval reportname, reportnamealt;
+ mval trigjrec;
+ char *trigjrecptr;
+ int trigjreclen;
io_pair io_save_device;
int4 max_xecute_size;
boolean_t no_error;
@@ -1108,13 +1115,26 @@ boolean_t trigger_update_rec(char *trigger_rec, uint4 len, boolean_t noprompt, u
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
+ assert(dollar_tlevel);
assert(0 > memcmp(LITERAL_HASHLABEL, LITERAL_MAXHASHVAL, MIN(STRLEN(LITERAL_HASHLABEL), STRLEN(LITERAL_MAXHASHVAL))));
assert(0 > memcmp(LITERAL_HASHCOUNT, LITERAL_MAXHASHVAL, MIN(STRLEN(LITERAL_HASHCOUNT), STRLEN(LITERAL_MAXHASHVAL))));
assert(0 > memcmp(LITERAL_HASHCYCLE, LITERAL_MAXHASHVAL, MIN(STRLEN(LITERAL_HASHCYCLE), STRLEN(LITERAL_MAXHASHVAL))));
assert(0 > memcmp(LITERAL_HASHTNAME, LITERAL_MAXHASHVAL, MIN(STRLEN(LITERAL_HASHTNAME), STRLEN(LITERAL_MAXHASHVAL))));
assert(0 > memcmp(LITERAL_HASHTNCOUNT, LITERAL_MAXHASHVAL, MIN(STRLEN(LITERAL_HASHTNCOUNT), STRLEN(LITERAL_MAXHASHVAL))));
- rec_num = (NULL == record_num) ? 0 : *record_num;
+ rec_num = ((NULL == record_num)? 0 : *record_num);
gvinit();
+ trigjrec.mvtype = MV_STR;
+ trigjrec.str.len = len;
+ trigjrec.str.addr = trigger_rec;
+ if (NULL == trigfile_device)
+ { /* Check if this is a multi-line trigger. In that case, use just the first line for the below processing.
+ * The rest of the lines will later be copied over into values[XECUTE_SUB].
+ */
+ trigjrecptr = memchr(trigger_rec, '\n', len);
+ if (NULL != trigjrecptr)
+ len = trigjrecptr - trigger_rec;
+ } else
+ assert(NULL == memchr(trigger_rec, '\n', len));
if ((0 == len) || (COMMENT_LITERAL == *trigger_rec))
return TRIG_SUCCESS;
if (('-' != *trigger_rec) && ('+' != *trigger_rec))
@@ -1129,6 +1149,12 @@ boolean_t trigger_update_rec(char *trigger_rec, uint4 len, boolean_t noprompt, u
{
if ((1 == len) && ('*' == *trigger_rec))
{
+ if ((NULL == trigfile_device) && (NULL != trigjrecptr))
+ {
+ util_out_print_gtmio("Newline not allowed in trigger name for delete operation", FLUSH);
+ trig_stats[STATS_ERROR]++;
+ return TRIG_FAILURE;
+ }
if (!noprompt)
{
util_out_print("This operation will delete all triggers.", FLUSH);
@@ -1140,11 +1166,17 @@ boolean_t trigger_update_rec(char *trigger_rec, uint4 len, boolean_t noprompt, u
return TRIG_SUCCESS;
}
}
- trigger_delete_all();
+ trigger_delete_all(--trigger_rec, len + 1);
return TRIG_SUCCESS;
} else if ((0 == len) || ('^' != *trigger_rec))
{ /* if the length < 0 let trigger_delete_name respond with the error message */
- if (TRIG_FAILURE == (status = trigger_delete_name(trigger_rec, len, trig_stats)))
+ if ((NULL == trigfile_device) && (NULL != trigjrecptr))
+ {
+ util_out_print_gtmio("Newline not allowed in trigger name for delete operation", FLUSH);
+ trig_stats[STATS_ERROR]++;
+ return TRIG_FAILURE;
+ }
+ if (TRIG_FAILURE == (status = trigger_delete_name(--trigger_rec, len + 1, trig_stats)))
trig_stats[STATS_ERROR]++;
return status;
}
@@ -1174,43 +1206,81 @@ boolean_t trigger_update_rec(char *trigger_rec, uint4 len, boolean_t noprompt, u
COMPUTE_HASH_STR(&kill_trigger_hash);
if (multi_line_xecute)
{
- if (NULL == trigfile_device)
- {
- util_out_print_gtmio("Cannot use multi-line xecute in $ztrigger ITEM", FLUSH);
- return TRIG_FAILURE;
- }
- io_save_device = io_curr_device;
- io_curr_device = *trigfile_device;
- values[XECUTE_SUB] = xecute_buffer;
- value_len[XECUTE_SUB] = 0;
- max_xecute_size = SIZEOF(xecute_buffer);
- multi_line = multi_line_xecute;
- while (multi_line && (0 <= (rec_len = file_input_get(&trigger_rec))))
+ if (NULL != trigfile_device)
{
- rec_num++;
- io_curr_device = io_save_device; /* In case we have to write an error message */
- no_error &= trigger_parse(trigger_rec, (uint4)rec_len, trigvn, values, value_len, &max_xecute_size,
- &multi_line);
+ assert(SIZEOF(xecute_buffer) == MAX_BUFF_SIZE + MAX_XECUTE_LEN);
+ /* Leave MAX_BUFF_SIZE to store other (excluding XECUTE) parts of the trigger definition.
+ * This way we can copy over these once the multi-line XECUTE string is constructed and
+ * use this to write the TLGTRIG/ULGTRIG journal record in case we do "jnl_format" later.
+ */
+ values[XECUTE_SUB] = &xecute_buffer[MAX_BUFF_SIZE];
+ trigjreclen = trigjrec.str.len + 1; /* 1 for newline */
+ assert(trigjreclen < MAX_BUFF_SIZE);
+ trigjrecptr = &xecute_buffer[MAX_BUFF_SIZE - trigjreclen];
+ memcpy(trigjrecptr, trigjrec.str.addr, trigjreclen - 1);
+ trigjrecptr[trigjreclen - 1] = '\n';
+ trigjrec.str.addr = trigjrecptr;
+ value_len[XECUTE_SUB] = 0;
+ max_xecute_size = MAX_XECUTE_LEN;
+ io_save_device = io_curr_device;
io_curr_device = *trigfile_device;
- }
- if (NULL != record_num)
- *record_num = rec_num;
- if (!no_error)
- {
+ multi_line = multi_line_xecute;
+ while (multi_line && (0 <= (rec_len = file_input_get(&trigger_rec))))
+ {
+ rec_num++;
+ io_curr_device = io_save_device; /* In case we have to write an error message */
+ no_error &= trigger_parse(trigger_rec, (uint4)rec_len, trigvn, values, value_len,
+ &max_xecute_size, &multi_line);
+ io_curr_device = *trigfile_device;
+ }
+ trigjrec.str.len = trigjreclen + value_len[XECUTE_SUB];
+ if (NULL != record_num)
+ *record_num = rec_num;
+ if (!no_error)
+ {
+ io_curr_device = io_save_device;
+ trig_stats[STATS_ERROR]++;
+ return TRIG_FAILURE;
+ }
+ if (0 > rec_len)
+ {
+ io_curr_device = io_save_device;
+ util_out_print_gtmio("Multi-line trigger -XECUTE is not properly terminated", FLUSH);
+ trig_stats[STATS_ERROR]++;
+ return TRIG_FAILURE;
+ }
io_curr_device = io_save_device;
- trig_stats[STATS_ERROR]++;
- return TRIG_FAILURE;
+ } else
+ {
+ values[XECUTE_SUB] = trigjrecptr + 1;
+ value_len[XECUTE_SUB] = trigjrec.str.addr + trigjrec.str.len - (trigjrecptr + 1);
+ if ('\n' != values[XECUTE_SUB][value_len[XECUTE_SUB] - 1])
+ {
+ util_out_print_gtmio("Multi-line xecute in $ztrigger ITEM must end in newline", FLUSH);
+ trig_stats[STATS_ERROR]++;
+ return TRIG_FAILURE;
+ }
+ if (!process_xecute(values[XECUTE_SUB], &value_len[XECUTE_SUB], TRUE))
+ {
+ CONV_STR_AND_PRINT("Error parsing XECUTE string: ", value_len[XECUTE_SUB], values[XECUTE_SUB]);
+ trig_stats[STATS_ERROR]++;
+ return TRIG_FAILURE;
+ }
+ /* trigjrec is already properly set up */
}
- if (0 > rec_len)
+ STR_HASH(values[XECUTE_SUB], value_len[XECUTE_SUB], set_trigger_hash.hash_code, set_trigger_hash.hash_code);
+ STR_HASH(values[XECUTE_SUB], value_len[XECUTE_SUB], kill_trigger_hash.hash_code, kill_trigger_hash.hash_code);
+ } else if ((NULL == trigfile_device) && (NULL != trigjrecptr))
+ { /* If this is a not a multi-line xecute string, we dont expect newlines. The only exception is if it is
+ * the last byte in the string.
+ */
+ *trigjrecptr++;
+ if (trigjrecptr != (trigjrec.str.addr + trigjrec.str.len))
{
- io_curr_device = io_save_device;
- util_out_print_gtmio("Multi-line trigger -XECUTE is not properly terminated", FLUSH);
+ util_out_print_gtmio("Newline allowed only inside multi-line xecute in $ztrigger ITEM", FLUSH);
trig_stats[STATS_ERROR]++;
return TRIG_FAILURE;
}
- STR_HASH(values[XECUTE_SUB], value_len[XECUTE_SUB], set_trigger_hash.hash_code, set_trigger_hash.hash_code);
- STR_HASH(values[XECUTE_SUB], value_len[XECUTE_SUB], kill_trigger_hash.hash_code, kill_trigger_hash.hash_code);
- io_curr_device = io_save_device;
}
gvname.var_name.addr = trigvn;
gvname.var_name.len = trigvn_len;
@@ -1242,6 +1312,19 @@ boolean_t trigger_update_rec(char *trigger_rec, uint4 len, boolean_t noprompt, u
*/
csa->db_dztrigger_cycle++;
}
+ if (JNL_WRITE_LOGICAL_RECS(csa))
+ {
+ assert(!gv_cur_region->read_only);
+ /* Attach to jnlpool. Normally SET or KILL of the ^#t records take care of this but in case this is a NO-OP
+ * trigger operation that wont happen and we still want to write a TLGTRIG/ULGTRIG journal record. Hence
+ * the need to do this.
+ */
+ JNLPOOL_INIT_IF_NEEDED(csa, csa->hdr, csa->nl);
+ assert(dollar_tlevel);
+ T_BEGIN_SETORKILL_NONTP_OR_TP(ERR_TRIGLOADFAIL); /* needed to set update_trans TRUE on this region
+ * even if NO db updates happen to ^#t nodes. */
+ jnl_format(JNL_LGTRIG, NULL, &trigjrec, 0);
+ }
SET_GVTARGET_TO_HASHT_GBL(csa);
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
new_name = check_unique_trigger_name(trigvn, trigvn_len, values[TRIGNAME_SUB], value_len[TRIGNAME_SUB]);
diff --git a/sr_unix/trigger_user_name.c b/sr_unix/trigger_user_name.c
index d53ffdc..bd20959 100644
--- a/sr_unix/trigger_user_name.c
+++ b/sr_unix/trigger_user_name.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2010 Fidelity Information Services, Inc *
+ * Copyright 2010, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -49,7 +49,7 @@ int validate_input_trigger_name(char *trigger_name, uint4 trigger_name_len, bool
{
char *ptr, *tail;
uint4 len, name_len, num_len, max_len;
- boolean_t wild, poundtail;
+ boolean_t wild, poundtail, firstdigit;
if (0 == trigger_name_len)
/* reject zero lengths, use -1 because returning 0 for 0 won't signal an error */
@@ -65,12 +65,12 @@ int validate_input_trigger_name(char *trigger_name, uint4 trigger_name_len, bool
if (!ISALPHA_ASCII(*ptr) && ('%' != *ptr))
/* first char must be alpha or '%' sign */
return INTCAST(ptr - trigger_name);
+ name_len++; /* to record first alpha byte that has already been processed */
if ('*' == *tail)
- { /* strip the wild card to skip checking it */
+ { /* strip the wild card to skip checking it */
wild = TRUE;
tail--;
len--;
- name_len++;
} else
wild = FALSE;
if (wildcard_ptr)
@@ -79,11 +79,12 @@ int validate_input_trigger_name(char *trigger_name, uint4 trigger_name_len, bool
/* special case to return sooner for a single character name */
return INTCAST(ptr - trigger_name) + 1 + ((wild) ? 1 : 0);
if (trigger_user_name(trigger_name, trigger_name_len))
- /* user defined name, use MAX_USER_TRIGNAME_LEN as max_len */
+ { /* user defined name, use MAX_USER_TRIGNAME_LEN as max_len */
max_len = MAX_USER_TRIGNAME_LEN;
- else
- /* auto generated name, use MAX_AUTO_TRIGNAME_LEN as max_len */
- max_len = MAX_AUTO_TRIGNAME_LEN;
+ if (wild)
+ name_len++;
+ } else
+ max_len = MAX_AUTO_TRIGNAME_LEN; /* auto generated name, use MAX_AUTO_TRIGNAME_LEN as max_len */
poundtail = (TRIGNAME_SEQ_DELIM == *tail);
if (MAX_USER_TRIGNAME_LEN + ((poundtail) ? 1 : 0) < trigger_name_len)
/* name, must be under 28 chars (MAX_USER_TRIGNAME_LEN), but increment
@@ -104,8 +105,16 @@ int validate_input_trigger_name(char *trigger_name, uint4 trigger_name_len, bool
if (wild)
/* reject anything between the first # sign and wild card */
return INTCAST(ptr - trigger_name);
- while (++ptr <= tail && TRIGNAME_SEQ_DELIM != *ptr)
+ firstdigit = TRUE;
+ while ((++ptr <= tail) && (TRIGNAME_SEQ_DELIM != *ptr))
{ /* validate the numeric portion of the auto generated name */
+ if (firstdigit)
+ {
+ /* reject number starting with 0 as that is not possible in auto generated name */
+ if ('0' == *ptr)
+ return INTCAST(ptr - trigger_name);
+ firstdigit = FALSE;
+ }
if ((!ISDIGIT_ASCII(*ptr)) || (NUM_TRIGNAME_SEQ_CHARS < ++num_len))
/* reject non-numeric or reject aaa#1234567 */
return INTCAST(ptr - trigger_name);
diff --git a/sr_unix/ttt.txt b/sr_unix/ttt.txt
index 1dfd69c..4d753dc 100644
--- a/sr_unix/ttt.txt
+++ b/sr_unix/ttt.txt
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2001, 2013 Fidelity Information Services, Inc ;
+; Copyright 2001, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -428,9 +428,10 @@ OC_FNZPRIV: pushab val.0
OC_FNZQGBLMOD: pushab val.0
calls #1,xfer.xf_fnzqgblmod
OC_FNZSEA: pushab val.0
+ pushl val.3
pushl val.2
pushab val.1
- calls #3,xfer.xf_fnzsearch
+ calls #4,xfer.xf_fnzsearch
OC_FNZSETPRV: pushab val.0
pushab val.1
calls #2,xfer.xf_fnzsetprv
@@ -438,6 +439,9 @@ OC_FNZSIGPROC: pushab val.0
pushl val.2
pushl val.1
calls #3,xfer.xf_fnzsigproc
+OC_FNZSOCKET: irepab val.2
+ pushab val.0
+ calls val.1,xfer.xf_fnzsocket
OC_FNZSUBSTR: pushab val.0 ; Destination mval
pushl val.3 ; max byte length
pushl val.2 ; starting character position
@@ -829,7 +833,7 @@ OC_SETZBRK: pushl val.5
pushl val.2
pushab val.1
pushab val.3
- calls #5,xfer.xf_setzbrk
+ jsb xfer.xf_setzbrk ;calls #5,xfer.xf_setzbrk
OC_SETZEXTRACT: pushab val.0
pushl val.3
pushl val.2
@@ -1035,3 +1039,16 @@ OC_FNZPEEK: pushab val.0
pushl val.2
pushab val.1
calls #5,xfer.xf_fnzpeek
+OC_FNZSYSLOG: pushab val.0 ; destination mval
+ pushab val.1 ; string
+ calls #2,xfer.xf_fnzsyslog
+OC_RHD_EXT: pushab val.4
+ pushab val.3
+ pushab val.2
+ pushab val.1
+ calls #4,xfer.xf_rhd_ext
+ movl r0,addr.0
+OC_LAB_EXT: calls #0,xfer.xf_lab_ext
+ movl r0,addr.0
+OC_ZRUPDATE: irepab val.2 ; TODO: decide ??? opcode not + in sr_unix_nsb/ttt or sr_vvms/ttt ???
+ calls val.1,xfer.xf_zrupdate
diff --git a/sr_unix/urx_remove.c b/sr_unix/urx_remove.c
index 8c8334e..b21f1ae 100644
--- a/sr_unix/urx_remove.c
+++ b/sr_unix/urx_remove.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2002, 2010 Fidelity Information Services, Inc *
+ * Copyright 2002, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -31,13 +31,13 @@ void urx_remove(rhdtyp *rtnhdr)
urx_rtnref *rtn, *rtnprev;
urx_labref *lab, *labprev;
urx_addr *addr, *addrprev, *savaddr;
- char *regstart, *regend;
+ unsigned char *regstart, *regend;
int deletes;
DEBUG_ONLY(deletes = 0);
#ifdef USHBIN_SUPPORTED
/* All unresolved addresses will point into the linkage section */
- regstart = (char *)rtnhdr->linkage_adr;
+ regstart = (unsigned char *)rtnhdr->linkage_adr;
regend = regstart + (SIZEOF(lnk_tabent) * rtnhdr->linkage_len);
#else
/* All unresolved addresses will point into the code section */
diff --git a/sr_unix/util_exit_handler.c b/sr_unix/util_exit_handler.c
index c20ee63..0b2d64a 100644
--- a/sr_unix/util_exit_handler.c
+++ b/sr_unix/util_exit_handler.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -26,6 +26,7 @@
#include "secshr_db_clnup.h"
#include "gtmimagename.h"
#include "dpgbldir.h"
+#include "gtmcrypt.h"
GBLREF boolean_t need_core;
GBLREF boolean_t created_core;
@@ -67,6 +68,7 @@ void util_exit_handler()
gv_rundown();
print_exit_stats();
util_out_close();
+ GTMCRYPT_CLOSE;
if (need_core && !created_core)
DUMP_CORE;
}
diff --git a/sr_unix/util_help.c b/sr_unix/util_help.c
index 6a7cf15..46a91b9 100644
--- a/sr_unix/util_help.c
+++ b/sr_unix/util_help.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2013 Fidelity Information Services, Inc *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,16 +11,21 @@
#include "mdef.h"
#include "util_help.h"
+#include "gtm_limits.h" /* for GTM_PATH_MAX */
#include "gtm_stdio.h" /* for snprintf() */
#include "gtm_string.h" /* for strlen() */
#include "gtm_stdlib.h" /* for SYSTEM() */
#include "gtmimagename.h" /* for struct gtmImageName */
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
+LITREF gtmImageName gtmImageNames[];
error_def(ERR_TEXT);
+error_def(ERR_GTMDISTUNVERIF);
-#define HELP_CMD_STRING_SIZE 512
-#define EXEC_GTMHELP "$gtm_dist/mumps -run %%XCMD 'do ^GTMHELP(\"%s\",\"$gtm_dist/%shelp.gld\")'",
+#define HELP_CMD_STRING_SIZE 256 + GTM_PATH_MAX + GTM_PATH_MAX
+#define EXEC_GTMHELP "%s/mumps -run %%XCMD 'do ^GTMHELP(\"%s\",\"%s/%shelp.gld\")'",
#define UTIL_HELP_IMAGES 5
/* We need the first two entries for compatibility */
@@ -45,6 +50,9 @@ void util_help(void)
SETUP_THREADGBL_ACCESS;
assert(1 >= TREF(parms_cnt));
assert(GTM_IMAGE < image_type && UTIL_HELP_IMAGES > image_type);
+ if (!gtm_dist_ok_to_use)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4, LEN_AND_STR(gtm_dist),
+ gtmImageNames[image_type].imageNameLen, gtmImageNames[image_type].imageName);
if (0 == TREF(parms_cnt))
help_option = utilImageGLDs[INVALID_IMAGE];
else
@@ -53,9 +61,9 @@ void util_help(void)
assert((char *)-1L != (TAREF1(parm_ary, TREF(parms_cnt) - 1)));
help_option = (TAREF1(parm_ary, TREF(parms_cnt) - 1));
}
- SNPRINTF(help_cmd_string, SIZEOF(help_cmd_string),
- "$gtm_dist/mumps -run %%XCMD 'do ^GTMHELP(\"%s\",\"$gtm_dist/%shelp.gld\")'",
- help_option, utilImageGLDs[image_type]);
+ /* if help_cmd_string is not long enough, the following command will fail */
+ SNPRINTF(help_cmd_string, SIZEOF(help_cmd_string), EXEC_GTMHELP
+ gtm_dist, help_option, gtm_dist, utilImageGLDs[image_type]);
rc = SYSTEM(help_cmd_string);
if (0 != rc)
rts_error_csa(NULL, VARLSTCNT(5) ERR_TEXT, 2, RTS_ERROR_TEXT("HELP command error"), rc);
diff --git a/sr_unix/util_output.c b/sr_unix/util_output.c
index c44d38d..be3899a 100644
--- a/sr_unix/util_output.c
+++ b/sr_unix/util_output.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -53,8 +53,10 @@ GBLDEF boolean_t first_syslog = TRUE; /* Global for a process - not thread spec
GBLDEF char facility[MAX_INSTNAME_LEN + 100];
GBLREF io_pair io_std_device;
+GBLREF io_pair io_curr_device;
GBLREF boolean_t blocksig_initialized;
GBLREF sigset_t block_sigsent;
+GBLREF boolean_t err_same_as_out;
GBLREF jnlpool_ctl_ptr_t jnlpool_ctl;
GBLREF jnlpool_addrs jnlpool;
GBLREF boolean_t is_src_server;
@@ -616,9 +618,6 @@ void util_out_send_oper(char *addr, unsigned int len)
case DBCERTIFY_IMAGE:
img_type = "DBCERTIFY";
break;
- case GTM_SVC_DAL_IMAGE:
- img_type = "GTM_SVC_DAL";
- break;
case GTCM_SERVER_IMAGE:
img_type = "GTCM";
break;
@@ -727,11 +726,14 @@ void util_out_send_oper(char *addr, unsigned int len)
void util_out_print_vaparm(caddr_t message, int flush, va_list var, int faocnt)
{
- char fmt_buff[OUT_BUFF_SIZE]; /* needs to be same size as that of the util out buffer */
- caddr_t fmtc;
- int rc, count;
- char *fmt_top1, *fmt_top2; /* the top of the buffer after leaving 1 (and 2 bytes respectively) at the end */
- int util_avail_len;
+ char fmt_buff[OUT_BUFF_SIZE]; /* needs to be same size as that of the util out buffer */
+ caddr_t fmtc;
+ int rc, count;
+ char *fmt_top1, *fmt_top2; /* the top of the buffer after leaving 1 (and 2 bytes respectively) at the end */
+ int util_avail_len;
+ mstr flushtxt;
+ boolean_t use_stdio;
+ io_pair save_io_curr_device;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -746,6 +748,7 @@ void util_out_print_vaparm(caddr_t message, int flush, va_list var, int faocnt)
if (0 < util_avail_len)
TREF(util_outptr) = util_format(message, var, TREF(util_outptr), util_avail_len, faocnt);
}
+ use_stdio = (IS_MCODE_RUNNING && (NULL != io_std_device.out) && (tt != io_std_device.out->type) && err_same_as_out);
switch (flush)
{
case NOFLUSH:
@@ -753,7 +756,8 @@ void util_out_print_vaparm(caddr_t message, int flush, va_list var, int faocnt)
case RESET:
break;
case FLUSH:
- *(TREF(util_outptr))++ = '\n';
+ if (!use_stdio)
+ *(TREF(util_outptr))++ = '\n';
case OPER:
case SPRINT:
/* For all three of these actions we need to do some output buffer translation. In all cases a '%'
@@ -792,7 +796,20 @@ void util_out_print_vaparm(caddr_t message, int flush, va_list var, int faocnt)
switch (flush)
{
case FLUSH:
- FPRINTF(stderr, "%s", fmt_buff);
+ if (use_stdio)
+ {
+ assert(NULL != op_write_ptr);
+ flushtxt.addr = fmt_buff;
+ flushtxt.len = INTCAST(TREF(util_outptr) - TREF(util_outbuff_ptr));
+ save_io_curr_device = io_curr_device;
+ io_curr_device = io_std_device;
+ (io_std_device.out->disp_ptr->write)(&flushtxt);
+ io_curr_device = save_io_curr_device;
+ (io_std_device.out->disp_ptr->wteol)(1, io_std_device.out);
+ } else
+ {
+ FPRINTF(stderr, "%s", fmt_buff);
+ }
break;
case OPER:
util_out_send_oper(fmt_buff, UINTCAST(fmtc - fmt_buff));
@@ -869,12 +886,25 @@ void util_out_print_gtmio(caddr_t message, int flush, ...)
*/
void util_cond_flush(void)
{
+ boolean_t use_stdio, buffer_empty;
+ mval flushtxt;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- if (NULL != io_std_device.out && 0 < io_std_device.out->dollar.x && TREF(util_outptr) != TREF(util_outbuff_ptr))
- FPRINTF(stderr, "\n");
- if (TREF(util_outptr) != TREF(util_outbuff_ptr))
+ use_stdio = FALSE;
+ buffer_empty = TREF(util_outptr) == TREF(util_outbuff_ptr);
+ if (NULL != io_std_device.out)
+ {
+ use_stdio = IS_MCODE_RUNNING && (tt != io_std_device.out->type) && err_same_as_out;
+ if (0 < io_std_device.out->dollar.x)
+ {
+ if (use_stdio)
+ (io_std_device.out->disp_ptr->wteol)(1, io_std_device.out);
+ else if (!buffer_empty)
+ FPRINTF(stderr, "\n");
+ }
+ }
+ if (!buffer_empty)
util_out_print(NULL, FLUSH);
}
diff --git a/sr_unix/wcs_flu.c b/sr_unix/wcs_flu.c
index 5d64af9..0daea70 100644
--- a/sr_unix/wcs_flu.c
+++ b/sr_unix/wcs_flu.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -160,7 +160,7 @@ boolean_t wcs_flu(uint4 options)
{
bool success, was_crit;
boolean_t fix_in_wtstart, flush_hdr, jnl_enabled, sync_epoch, write_epoch, need_db_fsync, in_commit;
- boolean_t flush_msync, speedup_nobefore, clean_dbsync, return_early;
+ boolean_t flush_msync, speedup_nobefore, clean_dbsync, return_early, epoch_already_current;
unsigned int lcnt, pass;
int save_errno, wtstart_errno;
jnl_buffer_ptr_t jb;
@@ -215,6 +215,8 @@ boolean_t wcs_flu(uint4 options)
if (jnl_enabled)
{
jb = jpc->jnl_buff;
+ /* Assert that we aren't trying to flush a completed journal file */
+ assert(!jb->last_eof_written);
/* Assert that we never flush the cache in the midst of a database commit. The only exception is MUPIP RUNDOWN */
assert((csa->ti->curr_tn == csa->ti->early_tn) || in_mu_rndwn_file);
if (!jgbl.dont_reset_gbl_jrec_time)
@@ -244,6 +246,7 @@ boolean_t wcs_flu(uint4 options)
if (jnl_enabled)
{
assert(SS_NORMAL == jnl_status);
+ epoch_already_current = (jb->post_epoch_freeaddr == jb->freeaddr); /* crit held, so this stays valid */
if (return_early = (speedup_nobefore && !csd->jnl_before_image))
{ /* Finish easiest option first. This database has NOBEFORE image journaling and caller has asked for
* processing to be speeded up in that case. Write only an epoch record, dont do heavyweight flush or fsync
@@ -264,9 +267,12 @@ boolean_t wcs_flu(uint4 options)
*/
fileheader_sync(gv_cur_region);
assert(NULL != jpc);
- if (0 == jpc->pini_addr)
- jnl_put_jrt_pini(csa);
- JNL_WRITE_EPOCH_REC(csa, cnl, clean_dbsync);
+ if (!jgbl.mur_extract && !epoch_already_current)
+ {
+ if (0 == jpc->pini_addr)
+ jnl_put_jrt_pini(csa);
+ JNL_WRITE_EPOCH_REC(csa, cnl, clean_dbsync);
+ }
}
fsync_dskaddr = jb->fsync_dskaddr; /* take a local copy as it could change concurrently */
if (fsync_dskaddr != jb->freeaddr)
@@ -517,15 +523,16 @@ boolean_t wcs_flu(uint4 options)
if ((MAXJNLQIOLOCKWAIT / 2 == lcnt) || (MAXJNLQIOLOCKWAIT == lcnt))
performCASLatchCheck(&jb->io_in_prog_latch, TRUE);
}
- if (csd->jnl_before_image)
+ if (csd->jnl_before_image && !epoch_already_current)
jb->need_db_fsync = TRUE; /* for comments on need_db_fsync, see jnl_output_sp.c */
/* else the journal files do not support before images and hence can only be used for forward recovery. So skip
* fsync of the database (jb->need_db_fsync = FALSE) because we don't care if the on-disk db is up-to-date or not.
+ * Also skip the fsync if we aren't actually going to write an epoch.
*/
RELEASE_SWAPLOCK(&jb->io_in_prog_latch);
assert(!(JNL_FILE_SWITCHED(jpc)));
assert(jgbl.gbl_jrec_time);
- if (!jgbl.mur_extract)
+ if (!jgbl.mur_extract && !epoch_already_current)
{
if (0 == jpc->pini_addr)
jnl_put_jrt_pini(csa);
diff --git a/sr_unix/wcs_wtstart.c b/sr_unix/wcs_wtstart.c
index ac60613..2252737 100644
--- a/sr_unix/wcs_wtstart.c
+++ b/sr_unix/wcs_wtstart.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -112,6 +112,7 @@ GBLREF int reformat_buffer_len;
GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data *cs_data;
+GBLREF jnlpool_addrs jnlpool;
#ifdef DEBUG
GBLREF volatile int reformat_buffer_in_use;
GBLREF volatile int4 gtmMallocDepth;
@@ -169,7 +170,7 @@ int4 wcs_wtstart(gd_region *region, int4 writes)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
- if (ANTICIPATORY_FREEZE_AVAILABLE)
+ if (INST_FREEZE_ON_ERROR_POLICY)
PUSH_GV_CUR_REGION(region, sav_cur_region, sav_cs_addrs, sav_cs_data)
udi = FILE_INFO(region);
csa = &udi->s_addrs;
@@ -181,7 +182,7 @@ int4 wcs_wtstart(gd_region *region, int4 writes)
if (csa->in_wtstart)
{
BG_TRACE_ANY(csa, wrt_busy);
- if (ANTICIPATORY_FREEZE_AVAILABLE)
+ if (INST_FREEZE_ON_ERROR_POLICY)
POP_GV_CUR_REGION(sav_cur_region, sav_cs_addrs, sav_cs_data)
return err_status; /* Already here, get out */
}
@@ -197,7 +198,7 @@ int4 wcs_wtstart(gd_region *region, int4 writes)
{
DECR_INTENT_WTSTART(cnl);
BG_TRACE_ANY(csa, wrt_blocked);
- if (ANTICIPATORY_FREEZE_AVAILABLE)
+ if (INST_FREEZE_ON_ERROR_POLICY)
POP_GV_CUR_REGION(sav_cur_region, sav_cs_addrs, sav_cs_data)
ENABLE_INTERRUPTS(INTRPT_IN_WCS_WTSTART);
return err_status;
@@ -375,7 +376,10 @@ int4 wcs_wtstart(gd_region *region, int4 writes)
size = (((v15_blk_hdr_ptr_t)bp)->bsiz + 1) & ~1;
} else DEBUG_ONLY(if (GDSV6 == csr->ondsk_blkver))
size = (bp->bsiz + 1) & ~1;
- DEBUG_ONLY(else GTMASSERT);
+# ifdef DEBUG
+ else
+ assert(IS_GDS_BLK_DOWNGRADE_NEEDED(csr->ondsk_blkver) || (GDSV6 == csr->ondsk_blkver));
+# endif
if (csa->do_fullblockwrites)
size = ROUND_UP(size, csa->fullblockwrite_len);
assert(size <= csd->blk_size);
@@ -532,7 +536,7 @@ writes_completed:
GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, rts_error, seg->fname_len, seg->fname);
}
# endif
- if (ANTICIPATORY_FREEZE_AVAILABLE)
+ if (INST_FREEZE_ON_ERROR_POLICY)
POP_GV_CUR_REGION(sav_cur_region, sav_cs_addrs, sav_cs_data)
return err_status;
}
diff --git a/sr_unix/zhist.c b/sr_unix/zhist.c
new file mode 100644
index 0000000..3e333a7
--- /dev/null
+++ b/sr_unix/zhist.c
@@ -0,0 +1,113 @@
+/****************************************************************
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#include "mdef.h"
+
+#include "gtm_string.h"
+
+#include "min_max.h"
+#include <rtnhdr.h>
+#include "zhist.h"
+#include "gtmlink.h"
+
+#ifdef USHBIN_SUPPORTED /* This entire file */
+
+/* Routine called from op_rhd_ext() to determine if the routine being called needs to be relinked. To return TRUE,
+ * the following conditions must be met:
+ * 1. Auto-relinking must be enabled in the directory the routine was located in (which may be different from the
+ * directory of the current routine by the same name).
+ * 2. This must be a newer version of the routine than what is currently linked.
+ * 3. If the routine is on the stack, recursive relinks must be enabled.
+ *
+ * Parameters:
+ * - zhist - address of zro_hist block of the routine to check if needs relinking
+ *
+ * Output:
+ * - TRUE if new object code is (or may be) available - indicates op_rhd_ext() should relink
+ * FALSE if currently linked code is up-to-date
+ */
+boolean_t need_relink(rhdtyp *rtnhdr, zro_hist *zhist)
+{
+ zro_validation_entry *iter;
+ uint4 cur_cycle;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ assert(NULL != zhist); /* Should be called unless relinking is possible */
+ /* TODO: Do this check second, if below logic would return TRUE */
+ if ((LINK_NORECURSIVE == TREF(relink_allowed)) && on_stack(rtnhdr, NULL))
+ return FALSE; /* can't relink, or else we'll get LOADRUNNING */
+ /* If SET=$ZRO cycle has changed since validation list was compiled, recreate the list.... just fully relink */
+ /* TODO: Only relink when absolutely necessary. If routine has same hash in same location, don't relink */
+ if (zhist->zroutines_cycle != TREF(set_zroutines_cycle))
+ return TRUE;
+ /* Traverse list corresponding to zro entries */
+ for (iter = &zhist->base[0]; iter != zhist->end; iter++)
+ {
+ /* TODO: assert routine name near cycle_reladdr == current routine invocation */
+ cur_cycle = RELINKCTL_CYCLE_READ(iter->relinkctl_bkptr, iter->cycle_loc);
+ if (cur_cycle != iter->cycle)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Routine called from zro_search()
+ * zro_zhist_saverecent
+ * INPUT:
+ * array of history entries created during zro_search()
+ * OUTPUT:
+ * global variable TREF(recent_zhist), which is then "passed" to incr_link, which associates this history with routine hdr
+ */
+void zro_zhist_saverecent(zro_validation_entry *zhent, zro_validation_entry *zhent_base)
+{
+ int hist_len;
+ zro_hist *lcl_recent_zhist;
+ DCL_THREADGBL_ACCESS;
+
+ SETUP_THREADGBL_ACCESS;
+ /* Malloc and save zhist copy */
+ assert(NULL != zhent);
+ assert(NULL != zhent_base);
+ hist_len = zhent - zhent_base;
+ lcl_recent_zhist = (zro_hist *)malloc(SIZEOF(zro_hist) + SIZEOF(zro_validation_entry) * hist_len);
+ lcl_recent_zhist->zroutines_cycle = TREF(set_zroutines_cycle);
+ lcl_recent_zhist->end = &lcl_recent_zhist->base[0] + hist_len;
+ memcpy((char *)&lcl_recent_zhist->base[0], (char *)zhent_base, SIZEOF(zro_validation_entry) * hist_len);
+ TREF(recent_zhist) = lcl_recent_zhist;
+}
+
+/*
+ * zro_record_zhist
+ * INPUT:
+ * routine name
+ * $ZROUTINES entry identifier
+ * OUTPUT:
+ * cycle_addr
+ * current value at cycle_addr
+ * NOTE: both saved into current history entry, "zhent"
+ */
+void zro_record_zhist(zro_validation_entry *zhent, zro_ent *obj_container, mstr *rtnname)
+{
+ open_relinkctl_sgm *linkctl;
+ relinkrec_loc_t rec;
+ int len;
+
+ assert(NULL != obj_container);
+ linkctl = obj_container->relinkctl_sgmaddr;
+ assert(NULL != linkctl);
+ zhent->relinkctl_bkptr = linkctl;
+ assert(NULL != zhent);
+ rec = relinkctl_insert_record(linkctl, rtnname);
+ zhent->cycle_loc = rec;
+ zhent->cycle = RELINKCTL_CYCLE_READ(linkctl, zhent->cycle_loc);
+}
+#endif /* USHBIN_SUPPORTED */
diff --git a/sr_unix/zhist.h b/sr_unix/zhist.h
new file mode 100644
index 0000000..c2dc801
--- /dev/null
+++ b/sr_unix/zhist.h
@@ -0,0 +1,42 @@
+/****************************************************************
+ * *
+ * Copyright 2013, 2014 Fidelity Information Services, Inc *
+ * *
+ * This source code contains the intellectual property *
+ * of its copyright holder(s), and is made available *
+ * under a license. If you do not know the terms of *
+ * the license, please stop and do not read further. *
+ * *
+ ****************************************************************/
+
+#ifndef ZHIST_H_INCLUDED
+#define ZHIST_H_INCLUDED
+
+#include "relinkctl.h"
+#include "zroutinessp.h"
+
+/*
+ * Suppose, for example, $ZROUTINES="dir1 dir2 dir3".
+ * TODO: explain validation logic............
+ */
+
+typedef struct
+{
+ uint4 cycle; /* private copy */
+ relinkrec_loc_t cycle_loc; /* location of record containing shared copy */
+ open_relinkctl_sgm *relinkctl_bkptr;
+ /* backpointer to zro_ent? any reason for that? maybe debugging? */
+} zro_validation_entry;
+
+typedef struct
+{
+ uint4 zroutines_cycle; /* compare to set_zroutines_cycle */
+ zro_validation_entry *end; /* end - &base[0] = size of allocated validation array */
+ zro_validation_entry base[1]; /* base of allocated validation array */
+} zro_hist;
+
+boolean_t need_relink(rhdtyp *rtnhdr, zro_hist *zhist);
+void zro_zhist_saverecent(zro_validation_entry *zhent, zro_validation_entry *zhent_base);
+void zro_record_zhist(zro_validation_entry *zhent, zro_ent *obj_container, mstr *rtnname);
+
+#endif /* ZHIST_H_INCLUDED */
diff --git a/sr_unix/zlmov_lnames.c b/sr_unix/zlmov_lnames.c
index 12e4ce0..3f4fd56 100644
--- a/sr_unix/zlmov_lnames.c
+++ b/sr_unix/zlmov_lnames.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,6 +14,17 @@
#include <rtnhdr.h>
#ifdef USHBIN_SUPPORTED
+/* Routine to copy label names out of a shared object's literal text pool for a version of an object
+ * about to be released to allow label text to still be available for other routines who have links to
+ * the label table which has pointers to these label names. The label names are copied into malloc'd
+ * storage for the duration of that routine's life in this process.
+ *
+ * Parameter:
+ *
+ * - hdr - Routine header address whose label table needs to be saved.
+ *
+ * Future change (GTM-8144) would eliminate the need for this.
+ */
void zlmov_lnames(rhdtyp *hdr)
{
lab_tabent *lab_ent, *lab_bot, *lab_top;
@@ -23,18 +34,19 @@ void zlmov_lnames(rhdtyp *hdr)
lab_bot = hdr->labtab_adr;
lab_top = hdr->labtab_adr + hdr->labtab_len;
size = 0;
- assert(NULL != lab_bot && 0 == lab_bot->lab_name.len); /* The first label is null label */
+ assert((NULL != lab_bot) && (0 == lab_bot->lab_name.len)); /* The first label is null label */
+ /* Compute size of label names */
for (lab_ent = lab_bot + 1; lab_ent < lab_top; lab_ent++)
{
- assert(lab_ent->lab_name.addr >= (char *)hdr->literal_text_adr &&
- lab_ent->lab_name.addr < (char *)(hdr->literal_text_adr + hdr->literal_text_len));
+ assert((lab_ent->lab_name.addr >= (char *)hdr->literal_text_adr)
+ && (lab_ent->lab_name.addr < (char *)(hdr->literal_text_adr + hdr->literal_text_len)));
size += lab_ent->lab_name.len;
}
lab_ptr = (char *)malloc(size);
- /* Previously, we would store the pointer to this malloc'd area in literal_text_adr so it could be accessable from the
- * routine header. However, we never use the field (e.g., to free it), so there's no point in saving it. With dynamic
- * literals, we still need literal_text_adr, so let's not do that.
+ /* Store address of malloc'd label text block in the routine header so we can find it to release it on an unlink-all
+ * (ZGOTO 0:entryref).
*/
+ hdr->lbltext_ptr = (unsigned char *)lab_ptr;
for (lab_ent = lab_bot + 1; lab_ent < lab_top; lab_ent++)
{
memcpy(lab_ptr, lab_ent->lab_name.addr, lab_ent->lab_name.len);
diff --git a/sr_unix/zro_load.c b/sr_unix/zro_load.c
index 3a4d7df..85cd19b 100644
--- a/sr_unix/zro_load.c
+++ b/sr_unix/zro_load.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -11,11 +11,11 @@
#include "mdef.h"
+#include <errno.h>
#include "gtm_string.h"
#include "gtm_stat.h"
#include "gtm_stdlib.h"
-#include <errno.h>
#include "io.h"
#include "iosp.h"
#include "zroutines.h"
@@ -23,8 +23,10 @@
#include "eintr_wrappers.h"
#include "error.h"
#include "zro_shlibs.h"
+#include "zhist.h"
+#include "gtm_limits.h"
-#define GETTOK toktyp = zro_gettok(&lp, top, &tok)
+#define GETTOK zro_gettok(&lp, top, &tok)
error_def(ERR_DIRONLY);
error_def(ERR_FILEPARSE);
@@ -35,10 +37,20 @@ error_def(ERR_NOLBRSRC);
error_def(ERR_QUALEXP);
error_def(ERR_ZROSYNTAX);
-void zro_load (mstr *str)
+/* Routine to parse the value of $ZROUTINES and create the list of structures that define the (new) routine
+ * search list order and define which (if any) directories can use auto-relink.
+ *
+ * Parameter:
+ * str - string to parse (usually dollar_zroutines)
+ *
+ * Return code:
+ * none
+ */
+void zro_load(mstr *str)
{
unsigned toktyp, status;
- mstr tok;
+ boolean_t enable_autorelink;
+ mstr tok, transtr;
char *lp, *top;
zro_ent array[ZRO_MAX_ENTS], *op;
int oi, si, total_ents;
@@ -49,19 +61,18 @@ void zro_load (mstr *str)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
+ (TREF(set_zroutines_cycle))++; /* Signal need to recompute zroutines histories for each linked routine */
memset(array, 0, SIZEOF(array));
lp = str->addr;
top = lp + str->len;
- while (lp < top && *lp == ZRO_DEL) /* Bypass leading blanks */
+ while ((lp < top) && (ZRO_DEL == *lp)) /* Bypass leading blanks */
lp++;
-
array[0].type = ZRO_TYPE_COUNT;
array[0].count = 0;
memset(&pblk, 0, SIZEOF(pblk));
pblk.buffer = tranbuf;
-
- GETTOK;
- if (toktyp == ZRO_EOL)
+ toktyp = GETTOK;
+ if (ZRO_EOL == toktyp)
{ /* Null string - set default */
array[0].count = 1;
array[1].type = ZRO_TYPE_OBJECT;
@@ -75,108 +86,139 @@ void zro_load (mstr *str)
{ /* String supplied - parse it */
for (oi = 1;;)
{
- if (toktyp != ZRO_IDN)
- rts_error(VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FSEXP);
- if (oi + 1 >= ZRO_MAX_ENTS)
- rts_error(VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_MAXARGCNT, 1, ZRO_MAX_ENTS);
- if (tok.len >= SIZEOF(tranbuf))
- rts_error(VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr);
- pblk.buff_size = MAX_FBUFF;
+ if (ZRO_IDN != toktyp)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FSEXP);
+ if (ZRO_MAX_ENTS <= (oi + 1))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_MAXARGCNT, 1,
+ ZRO_MAX_ENTS);
+ /* We have type ZRO_IDN (an identifier/name of some sort). See if token has a "*" (ZRO_ALF) at the end
+ * of it indicating that it is supposed to (1) be a directory and not a shared library and (2) that the
+ * user desires this directory to have auto-relink capability.
+ */
+ enable_autorelink = FALSE;
+# ifdef USHBIN_SUPPORTED
+ /* Only shared binary platforms recognize the auto-relink indicator. Specifying "*" at end of other
+ * directories causes an error further downstream (FILEPARSE) when the "*" is not stipped off the file
+ * name - unless someone has managed to create a directory with a "*" suffix.
+ */
+ if (ZRO_ALF == *(tok.addr + tok.len - 1))
+ { /* Auto-relink is indicated */
+ enable_autorelink = TRUE;
+ --tok.len; /* Remove indicator from name so we can use it */
+ assert(0 <= tok.len);
+ }
+# endif
+ if (SIZEOF(tranbuf) <= tok.len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, tok.len, tok.addr);
+ /* Run specified directory through parse_file to fill in any missing pieces and get some info on it */
+ pblk.buff_size = MAX_FBUFF; /* Don't count null terminator here */
pblk.fnb = 0;
status = parse_file(&tok, &pblk);
if (!(status & 1))
- rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_FILEPARSE, 2, tok.len, tok.addr, status);
-
- tranbuf[pblk.b_esl] = 0;
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, tok.len, tok.addr, status);
+ tranbuf[pblk.b_esl] = 0; /* Needed for some subsequent STAT_FILE */
STAT_FILE(tranbuf, &outbuf, stat_res);
if (-1 == stat_res)
- rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FILEPARSE, 2, tok.len, tok.addr,
- errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, tok.len, tok.addr, errno);
if (S_ISREG(outbuf.st_mode))
- { /* regular file - a shared library file */
+ { /* Regular file - a shared library file */
+ if (enable_autorelink)
+ /* Auto-relink indicator on shared library not permitted */
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, tok.len, tok.addr);
array[oi].shrlib = zro_shlibs_find(tranbuf);
array[oi].type = ZRO_TYPE_OBJLIB;
si = oi + 1;
} else
{
if (!S_ISDIR(outbuf.st_mode))
- rts_error(VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_INVZROENT, 2,
- tok.len, tok.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_INVZROENT, 2, tok.len, tok.addr);
array[oi].type = ZRO_TYPE_OBJECT;
array[oi + 1].type = ZRO_TYPE_COUNT;
si = oi + 2;
+# ifdef USHBIN_SUPPORTED
+ if (enable_autorelink)
+ { /* Only setup autorelink struct if it is enabled */
+ transtr.addr = tranbuf;
+ transtr.len = pblk.b_esl;
+ array[oi].relinkctl_sgmaddr = (void_ptr_t)relinkctl_attach(&transtr);
+ }
+# endif
}
array[0].count++;
array[oi].str = tok;
- GETTOK;
- if (toktyp == ZRO_LBR)
+ toktyp = GETTOK;
+ if (ZRO_LBR == toktyp)
{
- if (array[oi].type == ZRO_TYPE_OBJLIB)
- rts_error(VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_NOLBRSRC);
-
- GETTOK;
- if (toktyp == ZRO_DEL)
- GETTOK;
- if (toktyp != ZRO_IDN && toktyp != ZRO_RBR)
- rts_error(VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_QUALEXP);
-
+ if (ZRO_TYPE_OBJLIB == array[oi].type)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_NOLBRSRC);
+ toktyp = GETTOK;
+ if (ZRO_DEL == toktyp)
+ toktyp = GETTOK;
+ if ((ZRO_IDN != toktyp) && (ZRO_RBR != toktyp))
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_QUALEXP);
array[oi + 1].count = 0;
for (;;)
{
- if (toktyp == ZRO_RBR)
+ if (ZRO_RBR == toktyp)
break;
- if (toktyp != ZRO_IDN)
- rts_error(VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr, ERR_FSEXP);
- if (si >= ZRO_MAX_ENTS)
- rts_error(VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_MAXARGCNT, 1, ZRO_MAX_ENTS);
- if (tok.len >= SIZEOF(tranbuf))
- rts_error(VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_FILEPARSE, 2, tok.len, tok.addr);
+ if (ZRO_IDN != toktyp)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FSEXP);
+ if (ZRO_MAX_ENTS <= si)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_MAXARGCNT, 1, ZRO_MAX_ENTS);
+ if (SIZEOF(tranbuf) <= tok.len)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, tok.len, tok.addr);
pblk.buff_size = MAX_FBUFF;
pblk.fnb = 0;
status = parse_file(&tok, &pblk);
if (!(status & 1))
- rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_FILEPARSE, 2, tok.len, tok.addr, status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, tok.len, tok.addr, status);
tranbuf[pblk.b_esl] = 0;
STAT_FILE(tranbuf, &outbuf, stat_res);
if (-1 == stat_res)
- rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_FILEPARSE, 2, tok.len, tok.addr, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, tok.len, tok.addr, errno);
if (!S_ISDIR(outbuf.st_mode))
- rts_error(VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_DIRONLY, 2, tok.len, tok.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_DIRONLY, 2, tok.len, tok.addr);
array[oi + 1].count++;
array[si].type = ZRO_TYPE_SOURCE;
array[si].str = tok;
si++;
- GETTOK;
- if (toktyp == ZRO_DEL)
- GETTOK;
+ toktyp = GETTOK;
+ if (ZRO_DEL == toktyp)
+ toktyp = GETTOK;
}
- GETTOK;
+ toktyp = GETTOK;
} else
{
- if ((array[oi].type != ZRO_TYPE_OBJLIB) && (toktyp == ZRO_DEL || toktyp == ZRO_EOL))
+ if ((ZRO_TYPE_OBJLIB != array[oi].type) && ((ZRO_DEL == toktyp) || (ZRO_EOL == toktyp)))
{
- if (si >= ZRO_MAX_ENTS)
- rts_error(VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_MAXARGCNT, 1, ZRO_MAX_ENTS);
+ if (ZRO_MAX_ENTS <= si)
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_MAXARGCNT, 1, ZRO_MAX_ENTS);
array[oi + 1].count = 1;
array[si] = array[oi];
array[si].type = ZRO_TYPE_SOURCE;
si++;
}
}
- if (toktyp == ZRO_EOL)
+ if (ZRO_EOL == toktyp)
break;
-
- if (toktyp == ZRO_DEL)
- GETTOK;
+ if (ZRO_DEL == toktyp)
+ toktyp = GETTOK;
else
- rts_error(VARLSTCNT(4) ERR_ZROSYNTAX, 2, str->len, str->addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZROSYNTAX, 2, str->len, str->addr);
oi = si;
}
}
@@ -188,16 +230,16 @@ void zro_load (mstr *str)
assert(oi);
for (op = TREF(zro_root) + 1; oi-- > 0; )
{ /* release space held by translated entries */
- assert(op->type == ZRO_TYPE_OBJECT || op->type == ZRO_TYPE_OBJLIB);
+ assert((ZRO_TYPE_OBJECT == op->type) || (ZRO_TYPE_OBJLIB == op->type));
if (op->str.len)
free(op->str.addr);
- if ((op++)->type == ZRO_TYPE_OBJLIB)
+ if (ZRO_TYPE_OBJLIB == (op++)->type)
continue; /* i.e. no sources for shared library */
- assert(op->type == ZRO_TYPE_COUNT);
+ assert(ZRO_TYPE_COUNT == op->type);
si = (op++)->count;
for ( ; si-- > 0; op++)
{
- assert(op->type == ZRO_TYPE_SOURCE);
+ assert(ZRO_TYPE_SOURCE == op->type);
if (op->str.len)
free(op->str.addr);
}
@@ -211,36 +253,34 @@ void zro_load (mstr *str)
assert(oi);
for (op = TREF(zro_root) + 1; oi-- > 0; )
{
- assert(op->type == ZRO_TYPE_OBJECT || op->type == ZRO_TYPE_OBJLIB);
+ assert((ZRO_TYPE_OBJECT == op->type) || (ZRO_TYPE_OBJLIB == op->type));
if (op->str.len)
{
pblk.buff_size = MAX_FBUFF;
pblk.fnb = 0;
status = parse_file(&op->str, &pblk);
if (!(status & 1))
- rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_FILEPARSE, 2, op->str.len, op->str.addr, status);
-
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, op->str.len, op->str.addr, status);
op->str.addr = (char *)malloc(pblk.b_esl);
op->str.len = pblk.b_esl;
memcpy(op->str.addr, pblk.buffer, pblk.b_esl);
}
- if ((op++)->type == ZRO_TYPE_OBJLIB)
+ if (ZRO_TYPE_OBJLIB == (op++)->type)
continue;
- assert(op->type == ZRO_TYPE_COUNT);
+ assert(ZRO_TYPE_COUNT == op->type);
si = (op++)->count;
for ( ; si-- > 0; op++)
{
- assert(op->type == ZRO_TYPE_SOURCE);
+ assert(ZRO_TYPE_SOURCE == op->type);
if (op->str.len)
{
pblk.buff_size = MAX_FBUFF;
pblk.fnb = 0;
status = parse_file(&op->str, &pblk);
if (!(status & 1))
- rts_error(VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
- ERR_FILEPARSE, 2, op->str.len, op->str.addr, status);
-
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_ZROSYNTAX, 2, str->len, str->addr,
+ ERR_FILEPARSE, 2, op->str.len, op->str.addr, status);
op->str.addr = (char *)malloc(pblk.b_esl);
op->str.len = pblk.b_esl;
memcpy(op->str.addr, pblk.buffer, pblk.b_esl);
diff --git a/sr_unix/zro_search.c b/sr_unix/zro_search.c
index 5fbd871..a8690f6 100644
--- a/sr_unix/zro_search.c
+++ b/sr_unix/zro_search.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -14,7 +14,6 @@
#include "gtm_string.h"
#include "gtm_stat.h"
#include "gtm_limits.h"
-
#include <errno.h>
#include "zroutines.h"
@@ -22,19 +21,24 @@
#include "error.h"
#include "lv_val.h" /* needed for "fgncal.h" */
#include "fgncal.h"
+#include "min_max.h"
+#ifdef USHBIN_SUPPORTED
+#include <rtnhdr.h> /* needed for "zhist.h" */
+#include "zhist.h"
+#endif
error_def (ERR_ZFILENMTOOLONG);
error_def (ERR_SYSCALL);
-/*
- * mstr *objstr; if NULL, do not search for object, else pointer to object file text string
- * zro_ent **objdir; NULL if objstr is NULL, otherwise, return pointer to associated object directory
- * objdir is NULL if object directory is not found
- * mstr *srcstr; like objstr, except for associated source program
- * zro_ent **srcdir; like objdir, except for associated source program directory
- * boolean_t skip; if TRUE, skip over shared libraries. If FALSE, probe shared libraries.
+/* TODO: description
+ * mstr *objstr; If NULL, do not search for object, else pointer to object file text string.
+ * zro_ent **objdir; NULL if objstr is NULL, otherwise, return pointer to associated object directory.
+ * Note objdir is NULL if object directory is not found.
+ * mstr *srcstr; Like objstr, except for associated source program.
+ * zro_ent **srcdir; Like objdir, except for associated source program directory.
+ * boolean_t skip; If TRUE, skip over shared libraries. If FALSE, probe shared libraries.
*/
-void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir, boolean_t skip)
+void zro_search(mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir, boolean_t skip)
{
uint4 status;
zro_ent *op, *sp, *op_result, *sp_result;
@@ -43,6 +47,10 @@ void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir,
struct stat outbuf;
int stat_res;
mstr rtnname;
+# ifdef USHBIN_SUPPORTED
+ zro_validation_entry zhent_base[ZRO_MAX_ENTS];
+ zro_validation_entry *zhent;
+# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -55,7 +63,8 @@ void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir,
op_result = sp_result = NULL;
objcnt = (TREF(zro_root))->count;
assert(objcnt);
- for (op = TREF(zro_root) + 1; !op_result && !sp_result && objcnt-- > 0; )
+ USHBIN_ONLY(zhent = &zhent_base[0]);
+ for (op = TREF(zro_root) + 1; !op_result && !sp_result && (0 < objcnt--); )
{
assert((ZRO_TYPE_OBJECT == op->type) || (ZRO_TYPE_OBJLIB == op->type));
if (objstr)
@@ -77,7 +86,7 @@ void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir,
continue;
}
if ((op->str.len + objstr->len + 2) > SIZEOF(objfn))
- rts_error(VARLSTCNT(4) ERR_ZFILENMTOOLONG, 2, op->str.len, op->str.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZFILENMTOOLONG, 2, op->str.len, op->str.addr);
obp = &objfn[0];
if (op->str.len)
{
@@ -92,9 +101,20 @@ void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir,
if (-1 == stat_res)
{
if (errno != ENOENT)
- rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("stat"), CALLFROM, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("stat"), CALLFROM,
+ errno);
} else
op_result = op;
+# ifdef USHBIN_SUPPORTED
+ if ((NULL != op) && (NULL != op->relinkctl_sgmaddr))
+ { /* If this directory is auto-relink enabled, make sure to track the usages */
+ rtnname.len = MIN(objstr->len - (int)STR_LIT_LEN(DOTOBJ), MAX_MIDENT_LEN);
+ memcpy(objfn, objstr->addr, rtnname.len);
+ objfn[rtnname.len] = '\0';
+ rtnname.addr = objfn;
+ zro_record_zhist(zhent++, op, &rtnname);
+ }
+# endif
}
if (srcstr)
{
@@ -110,7 +130,7 @@ void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir,
{
assert(sp->type == ZRO_TYPE_SOURCE);
if (sp->str.len + srcstr->len + 2 > SIZEOF(srcfn)) /* extra 2 for '/' & null */
- rts_error(VARLSTCNT(4) ERR_ZFILENMTOOLONG, 2, sp->str.len, sp->str.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZFILENMTOOLONG, 2, sp->str.len, sp->str.addr);
sbp = &srcfn[0];
if (sp->str.len)
{
@@ -125,7 +145,8 @@ void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir,
if (-1 == stat_res)
{
if (ENOENT != errno)
- rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("stat"), CALLFROM, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("stat"),
+ CALLFROM, errno);
} else
{
sp_result = sp;
@@ -141,6 +162,16 @@ void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir,
op++;
}
}
+# ifdef USHBIN_SUPPORTED
+ if ((NULL != op_result) && (NULL != op_result->relinkctl_sgmaddr))
+ /* If this directory is auto-relink enabled, make sure to track the usages */
+ zro_zhist_saverecent(zhent, &zhent_base[0]);
+ else
+ /* If didn't find a binary result, or we didn't find a relinkable routine, we have no "recent zhist" value
+ * to return so just clear it.
+ */
+ TREF(recent_zhist) = NULL;
+# endif
if (objdir)
*objdir = op_result;
if (srcdir)
diff --git a/sr_unix/zroutinessp.h b/sr_unix/zroutinessp.h
index b26b666..474e06b 100644
--- a/sr_unix/zroutinessp.h
+++ b/sr_unix/zroutinessp.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,6 +12,14 @@
#ifndef ZROUTINESSP_H_INCLUDED
#define ZROUTINESSP_H_INCLUDED
+/* Parse token types returned by zro_gettok() used when parsing $ZROUTINES values */
+#define ZRO_EOL 0 /* End of line */
+#define ZRO_IDN 1 /* Identifier/name - directory or file name */
+#define ZRO_DEL ' ' /* Delimiter (space) */
+#define ZRO_LBR '(' /* Left parenthesis denoting source directory list start */
+#define ZRO_RBR ')' /* Right parenthesis denoting source directory list end */
+#define ZRO_ALF '*' /* Auto-relink flag/indicator */
+
/* zro_ent fields are interpreted based on entry type:
* ZRO_TYPE_COUNT --> count indicates number of entries following
* this entry representing a list of source or object directories.
@@ -24,19 +32,16 @@ typedef struct zro_ent_type
{
uint4 type;
uint4 count;
- mstr str;
- void_ptr_t shrlib; /* used only on those platforms that generate shared images */
- void *shrsym; /* used only on those platforms that generate shared images */
+ mstr str; /* Path name; str.addr is malloc'd TODO: why malloc'd?*/
+ void_ptr_t shrlib; /* Result of dlopen(), if a shared library */
+ void_ptr_t shrsym; /* Placeholder for result of fgn_getrtn(), which we pass from zro_search() to
+ * incr_link().
+ */
+ void_ptr_t relinkctl_sgmaddr; /* Shared memory control structure associated with this $ZRO entry */
} zro_ent;
-#define ZRO_EOL 0
-#define ZRO_IDN 1
-#define ZRO_DEL ' '
-#define ZRO_LBR '('
-#define ZRO_RBR ')'
-
int zro_gettok(char **lp, char *top, mstr *tok);
void zsrch_clr(int indx);
-void zro_search (mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir, boolean_t skip);
+void zro_search(mstr *objstr, zro_ent **objdir, mstr *srcstr, zro_ent **srcdir, boolean_t skip);
#endif /* ZROUTINESSP_H_INCLUDED */
diff --git a/sr_unix/zshow_devices.c b/sr_unix/zshow_devices.c
index bff8b5a..f2d315e 100644
--- a/sr_unix/zshow_devices.c
+++ b/sr_unix/zshow_devices.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -48,14 +48,14 @@
static readonly char space_text[] = {' '};
+GBLREF boolean_t ctrlc_on, gtm_utf8_mode;
+GBLREF io_log_name *io_root_log_name;
+GBLREF io_pair *io_std_device;
+
LITREF mstr chset_names[];
LITREF nametabent dev_param_names[];
LITREF uint4 dev_param_index[];
LITREF zshow_index zshow_param_index[];
-GBLREF bool ctrlc_on;
-GBLREF io_log_name *io_root_log_name;
-GBLREF io_pair *io_std_device;
-GBLREF boolean_t gtm_utf8_mode;
void zshow_devices(zshow_out *output)
{
@@ -361,7 +361,13 @@ void zshow_devices(zshow_out *output)
{
ZS_PARM_SP(&v, zshow_fixed);
}
- if (rm_ptr->noread)
+# ifdef UNIX
+ else if (rm_ptr->stream)
+ {
+ ZS_PARM_SP(&v, zshow_stream);
+ }
+# endif
+ if (rm_ptr->read_only)
{
ZS_PARM_SP(&v, zshow_read);
}
@@ -485,6 +491,10 @@ void zshow_devices(zshow_out *output)
ZS_STR_OUT(&v, socket_text);
dsocketptr = (d_socket_struct *)l->iod->dev_sp;
ZS_ONE_OUT(&v, space_text);
+ if (!l->iod->wrap)
+ {
+ ZS_PARM_SP(&v, zshow_nowrap);
+ }
ZS_STR_OUT(&v, total_text);
MV_FORCE_MVAL(&m, (int)dsocketptr->n_socket);
mval_write(output, &m, FALSE);
diff --git a/sr_unix_cm/gtcm_exit.c b/sr_unix_cm/gtcm_exit.c
index 134c35a..5c33afd 100644
--- a/sr_unix_cm/gtcm_exit.c
+++ b/sr_unix_cm/gtcm_exit.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -33,6 +33,7 @@ static char rcsid[] = "$Header:$";
#include "gv_rundown.h" /* for gv_rundown() prototype */
#include "op.h" /* for op_unlock() and op_lkinit() prototype */
+#include "gtmcrypt.h"
GBLREF int4 gtcm_exi_condition;
@@ -46,5 +47,6 @@ void gtcm_exit()
rc_delete_cpt();
rc_rundown();
#endif
+ GTMCRYPT_CLOSE;
exit(gtcm_exi_condition);
}
diff --git a/sr_unix_cm/gtcm_init.c b/sr_unix_cm/gtcm_init.c
index 54b78ea..29c55ce 100644
--- a/sr_unix_cm/gtcm_init.c
+++ b/sr_unix_cm/gtcm_init.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -100,7 +100,7 @@ void gtcm_init(int argc, char_ptr_t argv[])
get_page_size();
gtm_wcswidth_fnptr = gtm_wcswidth;
# ifndef GTCM_DEBUG_NOBACKGROUND
- FORK_CLEAN(pid);
+ FORK(pid);
if (0 > pid)
{
save_errno = errno;
diff --git a/sr_unix_cm/gtcm_loop.c b/sr_unix_cm/gtcm_loop.c
index bfb0b16..21d811f 100644
--- a/sr_unix_cm/gtcm_loop.c
+++ b/sr_unix_cm/gtcm_loop.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -244,7 +244,7 @@ void gcore_server(void)
dump_rc_hist();
}
- FORK(pid); /* BYPASSOK: we are dumping a core, so no FORK_CLEAN needed */
+ FORK(pid);
if (pid < 0) /* fork error */
{
OMI_DBG((omi_debug,
diff --git a/sr_unix_cm/gtcm_main.c b/sr_unix_cm/gtcm_main.c
index 18ba950..dd65f30 100644
--- a/sr_unix_cm/gtcm_main.c
+++ b/sr_unix_cm/gtcm_main.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -22,7 +22,6 @@
#include "gtm_stdio.h"
#include "gtm_stdlib.h" /* for exit() */
#include "gtm_time.h" /* for time() */
-#include "gt_timer.h" /* for set_blocksig() */
#include <sys/types.h>
#include <signal.h>
@@ -30,10 +29,10 @@
#include "gtcm.h"
#include "error.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
#include "gtm_threadgbl_init.h"
#include "gtmimagename.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
+#include "gtm_startup_chk.h"
#include "send_msg.h"
#include "wbox_test_init.h"
@@ -87,9 +86,7 @@ int main(int argc, char_ptr_t argv[])
GTM_THREADGBL_INIT;
ctxt = NULL;
- set_blocksig();
- gtm_imagetype_init(GTCM_SERVER_IMAGE);
- gtm_env_init(); /* read in all environment variables before calling any function particularly malloc (from err_init below)*/
+ common_startup_init(GTCM_SERVER_IMAGE);
SPRINTF(image_id,"%s=gtcm_server", image_id);
# ifdef SEQUOIA
if (!set_pset())
@@ -97,6 +94,7 @@ int main(int argc, char_ptr_t argv[])
# endif
/* Initialize everything but the network */
err_init(gtcm_exit_ch);
+ gtm_chk_dist(argv[0]);
omi_errno = OMI_ER_NO_ERROR;
ctxt = ctxt;
ESTABLISH_RET(omi_dbms_ch, -1); /* any return value to signify error return */
diff --git a/sr_unix_cm/gtcm_play.c b/sr_unix_cm/gtcm_play.c
index 5d1de09..1034255 100644
--- a/sr_unix_cm/gtcm_play.c
+++ b/sr_unix_cm/gtcm_play.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -21,7 +21,6 @@
#include "gtm_stdio.h"
#include "gtm_stdlib.h" /* for exit() */
#include "gtm_time.h" /* for time() */
-#include "gt_timer.h" /* for set_blocksig() */
#include "gtm_fcntl.h"
#include "gtm_string.h" /* for strerror() */
#include <sys/types.h>
@@ -30,10 +29,9 @@
#include "gtcm.h"
#include "error.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
#include "gtm_threadgbl_init.h"
#include "gtmimagename.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#ifndef lint
static char rcsid[] = "$Header:$";
@@ -68,12 +66,6 @@ GBLREF int rc_nxact;
GBLREF int rc_nerrs;
#endif /* defined(GTCM_RC) */
-/* On OSF/1 (Digital Unix), pointers are 64 bits wide; the only exception to this is C programs for which one may
- * specify compiler and link editor options in order to use (and allocate) 32-bit pointers. However, since C is
- * the only exception and, in particular because the operating system does not support such an exception, the argv
- * array passed to the main program is an array of 64-bit pointers. Thus the C program needs to declare argv[]
- * as an array of 64-bit pointers and needs to do the same for any pointer it sets to an element of argv[].
- */
int main(int argc, char_ptr_t argv[])
{
omi_conn *cptr, conn;
@@ -82,9 +74,7 @@ int main(int argc, char_ptr_t argv[])
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- set_blocksig();
- gtm_imagetype_init(GTCM_SERVER_IMAGE);
- gtm_env_init(); /* read in all environment variables before calling any function particularly malloc (from err_init below)*/
+ common_startup_init(GTCM_SERVER_IMAGE);
/* Open the packet log file for playback */
if (1 == argc)
conn.fd = fileno(stdin);
diff --git a/sr_unix_cm/gtcm_rep_err.c b/sr_unix_cm/gtcm_rep_err.c
index a269d37..8c2c639 100644
--- a/sr_unix_cm/gtcm_rep_err.c
+++ b/sr_unix_cm/gtcm_rep_err.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -43,14 +43,17 @@ static char rcsid[] = "$Header:$";
#endif
#define GTCM_SERV_LOG "/log/gtcm_server.erlg"
-#define GTM_DIST_PATH "$gtm_dist"
GBLREF char *omi_service;
+GBLREF char gtm_dist[GTM_PATH_MAX];
+GBLREF boolean_t gtm_dist_ok_to_use;
STATICDEF boolean_t first_error = TRUE;
STATICDEF char fileName[GTM_PATH_MAX];
error_def(ERR_TEXT);
error_def(ERR_DISTPATHMAX);
+error_def(ERR_GTMDISTUNDEF);
+error_def(ERR_GTMDISTUNVERIF);
ZOS_ONLY(error_def(ERR_BADTAG);)
void gtcm_rep_err(char *msg, int errcode)
@@ -58,10 +61,9 @@ void gtcm_rep_err(char *msg, int errcode)
FILE *fp;
char outbuf[OUT_BUFF_SIZE];
time_t now;
- int status, retval;
- char *gtm_dist, *filebuf, *tag_emsg, *tmp_time;
+ int status, retval, gtm_dist_len;
+ char *filebuf, *tag_emsg, *tmp_time;
mstr tn;
- MSTR_DEF(val, strlen(GTM_DIST_PATH), GTM_DIST_PATH); /* BYPASSOK */
if ('\0' == msg[0])
sgtm_putmsg(outbuf, VARLSTCNT(2) errcode, 0);
@@ -70,18 +72,21 @@ void gtcm_rep_err(char *msg, int errcode)
if (first_error)
{
first_error = FALSE;
- filebuf = fileName;
- status = TRANS_LOG_NAME(&val, &tn, fileName, GTM_PATH_MAX, dont_sendmsg_on_log2long);
- if ((SS_LOG2LONG == status) || (tn.len + strlen(GTCM_SERV_LOG) >= GTM_PATH_MAX))
- {
- send_msg(VARLSTCNT(3) ERR_DISTPATHMAX, 1, GTM_PATH_MAX - strlen(GTCM_SERV_LOG));
- exit(ERR_DISTPATHMAX);
- } else if (SS_NORMAL == status)
- filebuf = strcat(fileName, GTCM_SERV_LOG);
+ if (gtm_dist_ok_to_use)
+ SNPRINTF(fileName, GTM_PATH_MAX, "%s%s", gtm_dist, GTCM_SERV_LOG);
else
{
- assert(SS_NOLOGNAM == status);
- SPRINTF(fileName, "%s%s", P_tmpdir, GTCM_SERV_LOG);
+ STRNLEN(gtm_dist, GTM_PATH_MAX, gtm_dist_len);
+ if (gtm_dist_len)
+ {
+ if (GTM_DIST_PATH_MAX <= gtm_dist_len)
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_DISTPATHMAX, 1, GTM_DIST_PATH_MAX);
+ else
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_GTMDISTUNVERIF, 4,
+ LEN_AND_STR(gtm_dist), LEN_AND_LIT("gtcm"));
+ } else
+ send_msg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GTMDISTUNDEF);
+ SNPRINTF(fileName, GTM_PATH_MAX, "%s%s", P_tmpdir, GTCM_SERV_LOG);
}
}
# ifdef __MVS__
diff --git a/sr_unix_cm/gtcm_shmclean.c b/sr_unix_cm/gtcm_shmclean.c
index f79d8df..39b57cc 100644
--- a/sr_unix_cm/gtcm_shmclean.c
+++ b/sr_unix_cm/gtcm_shmclean.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -199,4 +199,5 @@ int main(int argc, char_ptr_t argv[])
}
if (server == 1 && daemon == 0)
clean_mem(RC_CPT_PATH);
+ return 0;
}
diff --git a/sr_unix_cm/omi_prc_conn.c b/sr_unix_cm/omi_prc_conn.c
index 944890f..cb2d371 100644
--- a/sr_unix_cm/omi_prc_conn.c
+++ b/sr_unix_cm/omi_prc_conn.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -177,21 +177,20 @@ int omi_prc_conn(omi_conn *cptr, char *xend, char *buff, char *bend)
#if !(defined(SCO) || defined(__linux__) || defined(__CYGWIN__) || defined(__MVS__))
if (authenticate) /* verify password and user name */
{
-#ifdef SHADOWPW
- struct spwd *spass, *getspnam();
- struct stat buf;
-#endif
- struct passwd *pass;
- char *pw, *syspw;
+# ifdef SHADOWPW
+ struct spwd *spass, *getspnam();
+ struct stat buf;
+# endif
+ struct passwd *pass;
+ char *pw, *syspw;
- /* lowercase agent name */
- for(s = ag_name; *s; s++)
- if (ISUPPER_ASCII(*s))
- *s = TOLOWER(*s);
+ /* lowercase agent name */
+ for(s = ag_name; *s; s++)
+ *s = TOLOWER(*s);
#ifdef SHADOWPW
- if (!Stat("/etc/shadow", &buf))
- {
+ if (!Stat("/etc/shadow", &buf))
+ {
if ((spass = getspnam(ag_name)) == NULL)
{
if (errno)
@@ -206,39 +205,32 @@ int omi_prc_conn(omi_conn *cptr, char *xend, char *buff, char *bend)
return -OMI_ER_DB_USERNOAUTH;
}
syspw = spass->sp_pwdp;
- } else if ((pass = getpwnam(ag_name)) == NULL)
- {
- OMI_DBG((omi_debug, "%s: user %s not found in /etc/passwd\n",
- SRVR_NAME, ag_name));
- return -OMI_ER_DB_USERNOAUTH;
- } else
+ } else if ((pass = getpwnam(ag_name)) == NULL)
+ {
+ OMI_DBG((omi_debug, "%s: user %s not found in /etc/passwd\n",
+ SRVR_NAME, ag_name));
+ return -OMI_ER_DB_USERNOAUTH;
+ } else
syspw = pass->pw_passwd;
-
-
-
-#else /* ndef SHADOWPW */
- if ((pass = getpwnam(ag_name)) == NULL)
- {
+# else /* ndef SHADOWPW */
+ if ((pass = getpwnam(ag_name)) == NULL)
+ {
OMI_DBG((omi_debug, "%s: user %s not found in /etc/passwd\n",
SRVR_NAME, ag_name));
return -OMI_ER_DB_USERNOAUTH;
} else
syspw = pass->pw_passwd;
-
-#endif /* SHADOWPW */
-
- pw = (char *) crypt(ag_pass, syspw);
-
- if (strcmp(pw, syspw) != 0)
- {
- OMI_DBG((omi_debug, "%s: login attempt for user %s failed.\n",
- SRVR_NAME, ag_name));
- return -OMI_ER_DB_USERNOAUTH;
- }
+# endif /* SHADOWPW */
+ pw = (char *) crypt(ag_pass, syspw);
+ if (strcmp(pw, syspw) != 0)
+ {
+ OMI_DBG((omi_debug, "%s: login attempt for user %s failed.\n",
+ SRVR_NAME, ag_name));
+ return -OMI_ER_DB_USERNOAUTH;
+ }
}
#endif /* SCO or linux or cygwin or z/OS */
-
/* Server name (in) */
OMI_SI_READ(&ss_len, cptr->xptr);
cptr->xptr += ss_len.value;
@@ -252,11 +244,9 @@ int omi_prc_conn(omi_conn *cptr, char *xend, char *buff, char *bend)
OMI_SI_WRIT(0, bptr);
/* Server password (out) */
OMI_SI_WRIT(0, bptr);
-
/* Bounds checking */
if (cptr->xptr > xend || bptr >= bend)
return -OMI_ER_PR_INVMSGFMT;
-
/* Extensions (in) -- count through them */
OMI_SI_READ(&ext_cnt, cptr->xptr);
for (i = 0; i < ext_cnt.value; i++)
@@ -264,17 +254,16 @@ int omi_prc_conn(omi_conn *cptr, char *xend, char *buff, char *bend)
OMI_LI_READ(&ext, cptr->xptr);
cptr->exts |= (1 << (ext.value - 1));
}
-
/* Mask off extensions we don't support */
cptr->exts &= OMI_EXTENSIONS;
/* Negotiate extension combinations */
if (cptr->exts & OMI_XTF_RC && cptr->exts & OMI_XTF_BUNCH)
cptr->exts &= ~OMI_XTF_BUNCH;
-#ifdef GTCM_RC
+# ifdef GTCM_RC
if (cptr->exts & OMI_XTF_RC)
cptr->of = rc_oflow_alc();
-#endif /* defined(GTCM_RC) */
+# endif /* defined(GTCM_RC) */
/* Extensions (out) */
eptr = bptr;
@@ -302,14 +291,11 @@ int omi_prc_conn(omi_conn *cptr, char *xend, char *buff, char *bend)
}
/* Number of extensions */
OMI_SI_WRIT(i, eptr);
-
/* Bounds checking */
if (cptr->xptr > xend || bptr >= bend)
return -OMI_ER_PR_INVMSGFMT;
-
/* Change the state of the connection */
cptr->state = OMI_ST_CONN;
return (int)(bptr - buff);
-
}
diff --git a/sr_unix_cm/omi_prc_qry.c b/sr_unix_cm/omi_prc_qry.c
index c70fd29..85ec6da 100644
--- a/sr_unix_cm/omi_prc_qry.c
+++ b/sr_unix_cm/omi_prc_qry.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2007 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,12 +40,13 @@ int
omi_prc_qry(omi_conn *cptr, char *xend, char *buff, char *bend)
{
char *bptr, *eptr;
- int rv;
- omi_li len;
- mval v;
+ int rv;
+ omi_li len;
+ mval v;
+ mstr opstr;
uns_char *bgn1, *bgn2, *sbsp;
char *grp;
- int grl;
+ int grl;
bptr = buff;
@@ -99,7 +100,9 @@ omi_prc_qry(omi_conn *cptr, char *xend, char *buff, char *bend)
/* Subscripts */
for (grp += grl + 1; *grp; grp += strlen(grp) + 1) {
bgn2 = (uns_char *)bptr++;
- sbsp = gvsub2str((uchar_ptr_t)grp, (uchar_ptr_t)bptr, FALSE);
+ opstr.addr = bptr;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ sbsp = gvsub2str((uchar_ptr_t)grp, &opstr, FALSE);
grl = (int)(sbsp - (uns_char *)bptr);
OMI_SI_WRIT(grl, bgn2);
bptr += grl;
diff --git a/sr_unix_cm/rc_frmt_lck.c b/sr_unix_cm/rc_frmt_lck.c
index 83409ca..68a21fd 100644
--- a/sr_unix_cm/rc_frmt_lck.c
+++ b/sr_unix_cm/rc_frmt_lck.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2003 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -36,6 +36,7 @@ short *subcnt;
unsigned char *g, *g_top;
char *length, *start;
char buff[MAX_ZWR_KEY_SZ], *b_top, *b, *c_top, *sub_start;
+ mstr opstr;
c_top = c + max_size;
g = key;
@@ -65,7 +66,9 @@ short *subcnt;
if (*g == '\0') /* not a valid number or a string */
return -RC_BADXBUF;
- b_top = (char *)gvsub2str(g,(uchar_ptr_t)buff,FALSE);
+ opstr.addr = buff;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ b_top = (char *)gvsub2str(g, &opstr, FALSE);
sub_start = c;
for (b = buff; b < b_top;)
diff --git a/sr_unix_gnp/gtcm_gnp_server.c b/sr_unix_gnp/gtcm_gnp_server.c
index 45f4c0f..effc9a1 100644
--- a/sr_unix_gnp/gtcm_gnp_server.c
+++ b/sr_unix_gnp/gtcm_gnp_server.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,7 +40,6 @@
#include "gtmsource.h"
#include "gtmimagename.h"
#include "trans_log_name.h"
-#include "get_page_size.h"
#include "filestruct.h"
#include "jnl.h"
#include "gdskill.h"
@@ -76,9 +75,9 @@
#include "gtcm_gnp_pktdmp.h"
#include "util.h"
#include "getzdir.h"
-#include "gtm_env_init.h" /* for gtm_env_init() prototype */
#include "suspsigs_handler.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
+#include "gtm_startup_chk.h"
#include "gtm_threadgbl_init.h"
#include "fork_init.h"
#include "gt_timers_add_safe_hndlrs.h"
@@ -132,8 +131,6 @@ GBLDEF char gtcm_gnp_server_log[MAX_FN_LEN + 1];
/* the length is the orignal length */
GBLDEF int gtcm_gnp_log_path_len;
-OS_PAGE_SIZE_DECLARE
-
static uint4 closewait;
#define CM_SERV_WAIT_FOR_INPUT 100 /* ms */
@@ -189,7 +186,7 @@ static void gtcm_gnp_server_actions(void)
gtcm_remove_from_action_queue();
CMI_MUTEX_RESTORE;
if ((connection_struct *)INTERLOCK_FAIL == curr_entry)
- rts_error(VARLSTCNT(1) CMERR_CMINTQUE);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) CMERR_CMINTQUE);
if ((connection_struct *)EMPTY_QUEUE != curr_entry)
{
if (1 == (curr_entry->int_cancel.laflag & 1))
@@ -294,7 +291,7 @@ static void gtcm_gnp_server_actions(void)
if (SS_NORMAL == status)
{
GET_LONG(status, curr_entry->clb_ptr->mbf);
- rts_error(VARLSTCNT(3) ERR_BADGTMNETMSG, 1, status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_BADGTMNETMSG, 1, status);
}
break;
}
@@ -378,17 +375,14 @@ int main(int argc, char **argv, char **envp)
static boolean_t no_fork = FALSE;
GTM_THREADGBL_INIT;
- set_blocksig();
- gtm_imagetype_init(GTCM_GNP_SERVER_IMAGE);
- gtm_wcswidth_fnptr = gtm_wcswidth;
- gtm_env_init(); /* read in all environment variables */
+ common_startup_init(GTCM_GNP_SERVER_IMAGE);
gtmenvp = envp;
- getjobnum();
err_init(stop_image_conditional_core);
assert(0 == offsetof(gv_key, top)); /* for integrity of CM_GET_GVCURRKEY */
assert(2 == offsetof(gv_key, end)); /* for integrity of CM_GET_GVCURRKEY */
assert(4 == offsetof(gv_key, prev)); /* for integrity of CM_GET_GVCURRKEY */
GTM_ICU_INIT_IF_NEEDED; /* Note: should be invoked after err_init (since it may error out) and before CLI parsing */
+ gtm_chk_dist(argv[0]);
/* read comments in gtm.c for cli magic below */
cli_lex_setup(argc, argv);
if (1 < argc)
@@ -400,7 +394,7 @@ int main(int argc, char **argv, char **envp)
cli_lex_in_ptr->tp = cli_lex_in_ptr->in_str;
parse_ret = parse_cmd();
if (parse_ret && (EOF != parse_ret))
- rts_error(VARLSTCNT(4) parse_ret, 2, LEN_AND_STR(cli_err_str));
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) parse_ret, 2, LEN_AND_STR(cli_err_str));
service_len = (unsigned short)SIZEOF(service);
CMI_DESC_SET_POINTER(&service_descr, service);
service[0] = '\0';
@@ -424,7 +418,6 @@ int main(int argc, char **argv, char **envp)
gtcm_gnp_server_log[log_path_len] = '\0';
gtcm_open_cmerrlog();
assert(0 == EMPTY_QUEUE);
- get_page_size();
licensed = TRUE;
stp_init(STP_INITSIZE);
rts_stringpool = stringpool;
@@ -447,10 +440,11 @@ int main(int argc, char **argv, char **envp)
gtcm_connection = FALSE;
if (!no_fork)
{
- FORK_CLEAN(pid);
+ FORK(pid);
if (0 > pid)
{
- rts_error(VARLSTCNT(5) ERR_TEXT, 2, LEN_AND_LIT("Error forking gnp server into the background"), errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_TEXT, 2,
+ LEN_AND_LIT("Error forking gnp server into the background"), errno);
exit(-1);
}
else if (0 < pid)
@@ -472,8 +466,8 @@ int main(int argc, char **argv, char **envp)
SIZEOF(connection_struct), CM_MSG_BUF_SIZE + CM_BUFFER_OVERHEAD);
if (CMI_ERROR(status))
{
- gtm_putmsg(VARLSTCNT(7) ERR_NETFAIL, 0, ERR_TEXT, 2, LEN_AND_LIT("Network interface initialization failed"),
- status);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_NETFAIL, 0,
+ ERR_TEXT, 2, LEN_AND_LIT("Network interface initialization failed"), status);
exit(status);
}
atexit(gtcm_exi_handler);
diff --git a/sr_unix_nsb/obj_code.c b/sr_unix_nsb/obj_code.c
index 9751ba7..fce4e5c 100644
--- a/sr_unix_nsb/obj_code.c
+++ b/sr_unix_nsb/obj_code.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -48,6 +48,7 @@ GBLREF spdesc stringpool;
GBLREF char cg_phase; /* code generation phase */
GBLREF char cg_phase_last; /* previous code generation phase */
GBLREF int4 curr_addr, code_size;
+GBLREF char object_file_name[];
error_def(ERR_TEXT);
@@ -88,7 +89,9 @@ void obj_code (uint4 src_lines, void *checksum_ctx)
mline *mlx, *mly;
var_tabent *vptr;
int4 lnr_pad_len;
+ DCL_THREADGBL_ACCESS;
+ SETUP_THREADGBL_ACCESS;
assert(!run_time);
obj_init();
/* Define the routine name global symbol. */
@@ -122,6 +125,11 @@ void obj_code (uint4 src_lines, void *checksum_ctx)
rhead.lnrtab_ptr = code_size;
rhead.lnrtab_len = src_lines;
rhead.compiler_qlf = cmd_qlf.qlf;
+ if (cmd_qlf.qlf & CQ_EMBED_SOURCE)
+ {
+ rhead.routine_source_offset = TREF(routine_source_offset);
+ rhead.routine_source_length = (uint4)(stringpool.free - stringpool.base) - TREF(routine_source_offset);
+ }
rhead.temp_mvals = sa_temps[TVAL_REF];
rhead.temp_size = sa_temps_offset[TCAD_REF];
code_size += src_lines * SIZEOF(int4);
@@ -168,6 +176,8 @@ void obj_code (uint4 src_lines, void *checksum_ctx)
#endif
emit_literals();
close_object_file();
+ /* Ready to make object visible. Rename from tmp name to real routine name */
+ rename_tmp_object_file(object_file_name);
}
void cg_lab (mlabel *l, int4 base)
diff --git a/sr_unix_nsb/opcode_def.h b/sr_unix_nsb/opcode_def.h
index 4a6826b..4558040 100644
--- a/sr_unix_nsb/opcode_def.h
+++ b/sr_unix_nsb/opcode_def.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -341,3 +341,5 @@ OPCODE_DEF(OC_INDMERGE2, (OCT_NULL))
OPCODE_DEF(OC_LITC, (OCT_MVAL | OCT_EXPRLEAF))
OPCODE_DEF(OC_STOLITC, (OCT_NULL))
OPCODE_DEF(OC_FNZPEEK, (OCT_MVAL | OCT_EXPRLEAF))
+OPCODE_DEF(OC_FNZSYSLOG, (OCT_MVAL | OCT_EXPRLEAF))
+OPCODE_DEF(OC_FNZSOCKET, (OCT_MVAL | OCT_EXPRLEAF))
diff --git a/sr_unix_nsb/resolve_ref.c b/sr_unix_nsb/resolve_ref.c
index 1107f88..0435ab0 100644
--- a/sr_unix_nsb/resolve_ref.c
+++ b/sr_unix_nsb/resolve_ref.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -28,10 +28,11 @@ GBLREF mlabel *mlabtab;
GBLREF command_qualifier cmd_qlf;
GBLREF uint4 gtmDebugLevel;
+error_def(ERR_ACTLSTTOOLONG);
+error_def(ERR_FMLLSTMISSING);
error_def(ERR_LABELMISSING);
+error_def(ERR_LABELNOTFND);
error_def(ERR_LABELUNKNOWN);
-error_def(ERR_FMLLSTMISSING);
-error_def(ERR_ACTLSTTOOLONG);
int resolve_ref(int errknt)
{
@@ -96,7 +97,8 @@ int resolve_ref(int errknt)
stx_error(ERR_LABELMISSING, 2, mlbx->mvname.len, mlbx->mvname.addr);
TREF(source_error_found) = 0;
y = newtriple(OC_RTERROR);
- y->operand[0] = put_ilit(ERR_LABELUNKNOWN);
+ y->operand[0] = put_ilit(OC_JMP == x->opcode
+ ? ERR_LABELNOTFND : ERR_LABELUNKNOWN); /* special error for GOTO jmp */
y->operand[1] = put_ilit(TRUE); /* This is a subroutine/func reference */
n->oprval.tref = y;
n->oprclass = TJMP_REF;
@@ -177,7 +179,7 @@ int resolve_ref(int errknt)
/* If for example there are nested $SELECT routines feeding a value to a SET $PIECE/$EXTRACT, this nested checking is
* necessary to make sure no OC_PASSTHRUs remain in the parameter chain to get turned into OC_NOOPs that will
- * cause GTMASSERTs in emit_code.
+ * cause assertpro in emit_code.
*/
void resolve_tref(triple *curtrip, oprtype *opnd)
{
diff --git a/sr_unix_nsb/rtnhdr.h b/sr_unix_nsb/rtnhdr.h
index e8e65bf..295db6e 100644
--- a/sr_unix_nsb/rtnhdr.h
+++ b/sr_unix_nsb/rtnhdr.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -97,6 +97,10 @@ typedef struct rhead_struct
# endif
unsigned char checksum_md5[16]; /* 16-byte MD5 checksum of routine source code */
routine_source *source_code; /* source code used by $TEXT */
+ uint4 routine_source_offset; /* (updated) when compiled with EMBED_SOURCE: offset of M source within literal text
+ * pool; becomes absolute address in incr_link
+ */
+ uint4 routine_source_length; /* if compiled with EMBED_SOURCE: length of source text */
} rhdtyp;
/* Routine table entry */
@@ -154,5 +158,6 @@ rhdtyp *op_rhdaddr1(mval *name);
lnr_tabent *op_labaddr(rhdtyp *routine, mval *label, int4 offset);
void urx_resolve(rhdtyp *rtn, lab_tabent *lbl_tab, lab_tabent *lbl_top);
char *rtnlaboff2entryref(char *entryref_buff, mident *rtn, mident *lab, int offset);
+boolean_t on_stack(rhdtyp *rtnhdr, boolean_t *need_duplicate);
#endif /* RTNHDR_H_INCLUDED */
diff --git a/sr_unix_nsb/ttt.txt b/sr_unix_nsb/ttt.txt
index a633269..c50397d 100644
--- a/sr_unix_nsb/ttt.txt
+++ b/sr_unix_nsb/ttt.txt
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2001, 2013 Fidelity Information Services, Inc ;
+; Copyright 2001, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -413,9 +413,10 @@ OC_FNZPRIV: pushab val.0
OC_FNZQGBLMOD: pushab val.0
calls #1,xfer.xf_fnzqgblmod
OC_FNZSEA: pushab val.0
+ pushl val.3
pushl val.2
pushab val.1
- calls #3,xfer.xf_fnzsearch
+ calls #4,xfer.xf_fnzsearch
OC_FNZSETPRV: pushab val.0
pushab val.1
calls #2,xfer.xf_fnzsetprv
@@ -423,6 +424,9 @@ OC_FNZSIGPROC: pushab val.0
pushl val.2
pushl val.1
calls #3,xfer.xf_fnzsigproc
+OC_FNZSOCKET: irepab val.2
+ pushab val.0
+ calls val.1,xfer.xf_fnzsocket
OC_FNZTRNLNM: pushab val.0
pushab val.6
pushab val.5
@@ -1018,3 +1022,6 @@ OC_FNZPEEK: pushab val.0
pushl val.2
pushab val.1
calls #5,xfer.xf_fnzpeek
+OC_FNZSYSLOG: pushab val.0 ; destination mval
+ pushab val.1 ; string
+ calls #2,xfer.xf_fnzsyslog
diff --git a/sr_vms_cm/gtcm_server.c b/sr_vms_cm/gtcm_server.c
index 4edd131..b95e0a4 100644
--- a/sr_vms_cm/gtcm_server.c
+++ b/sr_vms_cm/gtcm_server.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,7 +40,6 @@
#include "desblk.h" /* for desblk structure */
#include "gtcmtr_protos.h"
#include "trans_log_name.h"
-#include "get_page_size.h"
#include "filestruct.h"
#include "jnl.h"
#include "gdskill.h"
@@ -79,7 +78,6 @@ LITREF char cm_prd_name[];
LITREF char cm_ver_name[];
LITREF int4 cm_prd_len;
LITREF int4 cm_ver_len;
-OS_PAGE_SIZE_DECLARE
#define GTCM_AST_OVRHD 4 /* init ast, read/write overlap, mbx, safety */
@@ -125,9 +123,8 @@ gtcm_server()
GTM_THREADGBL_INIT;
assert(0 == EMPTY_QUEUE); /* check so dont need gdsfhead everywhere */
- gtm_imagetype_init(GTCM_GNP_SERVER_IMAGE); /* Side-effect: Sets skip_dbtriggers to TRUE for non-trigger platforms */
+ common_startup_init(GTCM_GNP_SERVER_IMAGE); /* Side-effect: Sets skip_dbtriggers to TRUE for non-trigger platforms */
gtm_env_init(); /* read in all environment variables */
- get_page_size();
name1.addr = "GTCMSVRNAM";
name1.len = SIZEOF("GTCMSVRNAM") - 1;
status = trans_log_name(&name1, &name2, nbuff);
@@ -167,7 +164,6 @@ gtcm_server()
dver.dsc$b_dtype = DSC$K_DTYPE_T;
dver.dsc$b_class = DSC$K_CLASS_S;
dver.dsc$a_pointer= cm_ver_name;
- getjobnum();
ast_init();
licensed = TRUE;
lkid = 2;
@@ -215,7 +211,7 @@ gtcm_server()
sys$dclexh(>cm_exi_blk);
INVOKE_INIT_SECSHR_ADDRS;
initialize_pattern_table();
- assert(run_time); /* Should have been set by gtm_imagetype_init */
+ assert(run_time); /* Should have been set by common_startup_init */
while (!cm_shutdown)
{
if (blkdlist)
diff --git a/sr_vvms/bin_load.c b/sr_vvms/bin_load.c
index 297c434..5c206a0 100644
--- a/sr_vvms/bin_load.c
+++ b/sr_vvms/bin_load.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -103,6 +103,7 @@ void bin_load(uint4 begin, uint4 end, struct RAB *inrab, struct FAB *infab)
mname_entry gvname;
gvnh_reg_t *gvnh_reg;
gd_region *dummy_reg;
+ mstr opstr;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
@@ -449,7 +450,9 @@ void bin_load(uint4 begin, uint4 end, struct RAB *inrab, struct FAB *infab)
} else
TREF(transform) = FALSE;
/* convert the subscript to string format */
- end_buff = gvsub2str(src_buff, dest_buff, FALSE);
+ opstr.addr = dest_buff;
+ opstr.len = MAX_ZWR_KEY_SZ;
+ end_buff = gvsub2str(src_buff, &opstr, FALSE);
/* transform the string to the current subsc format */
TREF(transform) = TRUE;
tmp_mval.mvtype = MV_STR;
diff --git a/sr_vvms/ctrlc_set.c b/sr_vvms/ctrlc_set.c
index 7977960..cfe0822 100644
--- a/sr_vvms/ctrlc_set.c
+++ b/sr_vvms/ctrlc_set.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -29,16 +29,17 @@
* ------------------------------------------------------------------
*/
-GBLREF volatile char source_file_name[];
GBLREF int (* volatile xfer_table[])();
-GBLREF volatile bool ctrlc_on;
+GBLREF volatile boolean_t ctrlc_on;
+GBLREF volatile char source_file_name[];
GBLREF volatile int4 ctrap_action_is, outofband;
+error_def(ERR_LASTFILCMPLD);
+
ctrlc_set(int4 dummy_param)
{
int4 status;
msgtype message;
- error_def(ERR_LASTFILCMPLD);
if (!IS_MCODE_RUNNING)
{
@@ -55,8 +56,7 @@ ctrlc_set(int4 dummy_param)
{
status = sys$setef(efn_outofband);
assert(SS$_WASCLR == status);
- if (status != SS$_WASCLR && status != SS$_WASSET)
- GTMASSERT;
+ assertpro((SS$_WASCLR == status) || (SS$_WASSET == status));
ctrap_action_is = 0;
outofband = ctrlc;
xfer_table[xf_linefetch] = op_fetchintrrpt;
diff --git a/sr_vvms/dse.c b/sr_vvms/dse.c
index 2927834..ad8a387 100644
--- a/sr_vvms/dse.c
+++ b/sr_vvms/dse.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -46,17 +46,15 @@
#include "desblk.h" /* for desblk structure */
#include "util.h"
#include "dse.h"
-#include "getjobnum.h"
#include "patcode.h"
#include "generic_exit_handler.h"
#include "dfntmpmbx.h"
#include "ladef.h"
#include "ast_init.h"
-#include "get_page_size.h"
#include "init_secshr_addrs.h"
#include "dse_exit.h"
#include "gtm_env_init.h" /* for gtm_env_init() prototype */
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
GBLDEF block_id patch_curr_blk;
@@ -78,8 +76,6 @@ GBLREF boolean_t write_after_image;
error_def(ERR_CTRLC);
-OS_PAGE_SIZE_DECLARE
-
extern int DSE_CMD();
extern int CLI$DCL_PARSE();
extern int CLI$DISPATCH();
@@ -101,7 +97,7 @@ void dse(void)
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- gtm_imagetype_init(DSE_IMAGE);
+ common_startup_init(DSE_IMAGE);
gtm_env_init(); /* read in all environment variables */
TREF(transform) = TRUE;
TREF(no_spangbls) = TRUE; /* dse operates on a per-region basis irrespective of global mapping in gld */
@@ -111,8 +107,6 @@ void dse(void)
status =lp_id(&lkid);
if (SS$_NORMAL != status)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
- get_page_size();
- getjobnum();
INVOKE_INIT_SECSHR_ADDRS;
dfntmpmbx(lnm$group.len, lnm$group.addr);
ast_init();
diff --git a/sr_vvms/dse_cmd.cld b/sr_vvms/dse_cmd.cld
index 0a45c36..f856d88 100644
--- a/sr_vvms/dse_cmd.cld
+++ b/sr_vvms/dse_cmd.cld
@@ -1,3 +1,13 @@
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! !
+! Copyright 2014 Fidelity Information Services, Inc !
+! !
+! This source code contains the intellectual property !
+! of its copyright holder(s), and is made available !
+! under a license. If you do not know the terms of !
+! the license, please stop and do not read further. !
+! !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
MODULE DSE_CMD
DEFINE VERB add
@@ -336,6 +346,7 @@ DEFINE VERB save
DEFINE VERB shift
ROUTINE dse_shift
QUALIFIER backward NONNEGATABLE VALUE(REQUIRED)
+ QUALIFIER block NONNEGATABLE VALUE(REQUIRED)
QUALIFIER forward NONNEGATABLE VALUE(REQUIRED)
QUALIFIER offset NONNEGATABLE VALUE(REQUIRED)
diff --git a/sr_vvms/errorsp.h b/sr_vvms/errorsp.h
index 9b21458..da485f4 100644
--- a/sr_vvms/errorsp.h
+++ b/sr_vvms/errorsp.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -82,7 +82,8 @@ GBLREF int4 error_condition;
return SS$_NORMAL; \
}
-#define START_CH(flag_assert) error_def(ERR_TPRETRY); \
+#define START_CH(dummy ) \
+ error_def(ERR_TPRETRY); /* BYPASSOK */ \
DCL_THREADGBL_ACCESS; \
\
SETUP_THREADGBL_ACCESS; \
diff --git a/sr_vvms/gtm$compile.c b/sr_vvms/gtm$compile.c
index bcc53f1..3f3ee3f 100644
--- a/sr_vvms/gtm$compile.c
+++ b/sr_vvms/gtm$compile.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -41,16 +41,14 @@
#include "io.h"
#include "source_file.h"
#include "lmdef.h"
-#include "getjobnum.h"
#include "ast_init.h"
#include "comp_esc.h"
-#include "get_page_size.h"
#include "init_secshr_addrs.h"
#include "print_exit_stats.h"
#include "gtm_env_init.h" /* for gtm_env_init() prototype */
#include "gtm_threadgbl_init.h"
#include "gtmimagename.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
GBLREF int (*op_open_ptr)(mval *v, mval *p, int t, mval *mspace);
GBLREF boolean_t run_time;
@@ -62,8 +60,6 @@ GBLREF spdesc rts_stringpool, stringpool;
error_def (LP_NOCNFDB);
error_def (ERR_WILLEXPIRE);
-OS_PAGE_SIZE_DECLARE
-
LITREF char gtm_product[PROD];
LITREF int4 gtm_product_len;
LITREF char gtm_version[VERS];
@@ -92,7 +88,7 @@ int gtm$compile(void)
GTM_THREADGBL_INIT; /* This is the first C routine in the VMS compiler so do init here */
gtm_env_init(); /* read in all environment variables before any function call (particularly malloc) */
- gtm_imagetype_init(GTM_IMAGE); /* While compile-only, pretending GTM_IMAGE is sufficient */
+ common_startup_init(GTM_IMAGE); /* While compile-only, pretending GTM_IMAGE is sufficient */
op_open_ptr = op_open;
licensed = TRUE;
# ifdef NOLICENSE
@@ -113,8 +109,6 @@ int gtm$compile(void)
status = lp_licensed(h, &dprd, &dver, mdl, nid, &lid, &lic_x, &days, pak);
}
# endif
- get_page_size();
- getjobnum();
INVOKE_INIT_SECSHR_ADDRS;
if (1 == (status & 1)) /* licensing: license units */
status = LP_ACQUIRE(pak, lic_x, lid, &lkid);
@@ -136,7 +130,7 @@ int gtm$compile(void)
} else
{
licensed = FALSE;
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(VARLSTCNT(1) status);
}
# endif
glb_cmd_qlf.object_file.str.addr = obj_file;
diff --git a/sr_vvms/gtm$startup.c b/sr_vvms/gtm$startup.c
index f71b5cd..83e01c3 100644
--- a/sr_vvms/gtm$startup.c
+++ b/sr_vvms/gtm$startup.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -86,7 +86,7 @@
#include "gtm_logicals.h" /* for DISABLE_ALIGN_STRINGS */
#include "logical_truth_value.h"
#include "zwrite.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
#define FREE_RTNTBL_SPACE 17
@@ -135,7 +135,6 @@ GBLREF boolean_t mstr_native_align;
GBLREF void (*cache_table_relobjs)(void); /* Function pointer to call cache_table_rebuild() */
GBLREF symval *curr_symval;
GBLREF boolean_t skip_dbtriggers;
-OS_PAGE_SIZE_DECLARE
error_def(ERR_LINKVERSION);
error_def(ERR_WILLEXPIRE);
@@ -224,10 +223,10 @@ void gtm$startup(struct startup_vector *svec, boolean_t is_dal)
op_open_ptr = op_open;
unw_prof_frame_ptr = unw_prof_frame;
if (SIZEOF(*svec) != svec->argcnt)
- rts_error(VARLSTCNT(1) ERR_LINKVERSION);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_LINKVERSION);
if (!init_done)
{
- gtm_imagetype_init(GTM_IMAGE);
+ common_startup_init(GTM_IMAGE);
gtm_env_init(); /* read in all environment variables */
if ((!is_dal) && NULL != (TREF(mprof_env_gbl_name)).str.addr)
turn_tracing_on(TADR(mprof_env_gbl_name), TRUE, (TREF(mprof_env_gbl_name)).str.len > 0);
@@ -242,7 +241,6 @@ void gtm$startup(struct startup_vector *svec, boolean_t is_dal)
else
status = SS$_NORMAL;
# endif
- get_page_size();
/* note: for upward compatibility, missing values in the startup vector can be set to defaults */
get_proc_info(0, TADR(login_time), &image_count);
gtm_main_address = svec->gtm_main_inaddr;
@@ -301,7 +299,7 @@ void gtm$startup(struct startup_vector *svec, boolean_t is_dal)
iott_write_delay[0] = -svec->user_io_timer;
rts_stringpool = stringpool;
TREF(compile_time) = FALSE;
- assert(run_time); /* Should have been set by gtm_imagetype_init */
+ assert(run_time); /* Should have been set by common_startup_init */
/* Initialize alignment requirement for the runtime stringpool */
log_name.addr = DISABLE_ALIGN_STRINGS;
log_name.len = STR_LIT_LEN(DISABLE_ALIGN_STRINGS);
@@ -406,7 +404,7 @@ void gtm$startup(struct startup_vector *svec, boolean_t is_dal)
if (!TREF(local_collseq))
{
exi_condition = ERR_COLLATIONUNDEF;
- gtm_putmsg(VARLSTCNT(3) ERR_COLLATIONUNDEF, 1, lct);
+ gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_COLLATIONUNDEF, 1, lct);
op_halt();
}
} else
diff --git a/sr_vvms/gtmsource_process_ops.c b/sr_vvms/gtmsource_process_ops.c
index 852abf2..addfb52 100644
--- a/sr_vvms/gtmsource_process_ops.c
+++ b/sr_vvms/gtmsource_process_ops.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2006, 2013 Fidelity Information Services, Inc *
+ * Copyright 2006, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -80,8 +80,6 @@ error_def(ERR_REPLWARN);
error_def(ERR_TEXT);
error_def(ERR_UNIMPLOP);
-static unsigned char *tcombuff, *msgbuff, *filterbuff;
-
int gtmsource_est_conn()
{
int connection_attempts, alert_attempts, save_errno, status;
@@ -227,42 +225,38 @@ int gtmsource_est_conn()
int gtmsource_alloc_tcombuff(void)
{ /* Allocate buffer for TCOM, ZTCOM records */
- if (NULL == tcombuff)
+ if (NULL == gtmsource_tcombuff_start)
{
assert(NULL == gtmsource_tcombuff_start);
- tcombuff = (unsigned char *)malloc(gd_header->n_regions * TCOM_RECLEN + OS_PAGE_SIZE);
- gtmsource_tcombuff_start = (unsigned char *)ROUND_UP2((unsigned long)tcombuff, OS_PAGE_SIZE);
+ gtmsource_tcombuff_start = (unsigned char *)malloc(gd_header->n_regions * TCOM_RECLEN);
}
return (SS_NORMAL);
}
void gtmsource_free_tcombuff(void)
{
- if (NULL != tcombuff)
+ if (NULL != gtmsource_tcombuff_start)
{
- free(tcombuff);
- tcombuff = gtmsource_tcombuff_start = NULL;
+ free(gtmsource_tcombuff_start);
+ gtmsource_tcombuff_start = NULL;
}
return;
}
int gtmsource_alloc_filter_buff(int bufsiz)
{
- unsigned char *old_filter_buff, *free_filter_buff;
+ unsigned char *old_filter_buff;
- bufsiz = ROUND_UP2(bufsiz, OS_PAGE_SIZE);
- if (gtmsource_filter != NO_FILTER && bufsiz > repl_filter_bufsiz)
+ if ((NO_FILTER != gtmsource_filter) && (bufsiz > repl_filter_bufsiz))
{
REPL_DPRINT3("Expanding filter buff from %d to %d\n", repl_filter_bufsiz, bufsiz);
- free_filter_buff = filterbuff;
old_filter_buff = repl_filter_buff;
- filterbuff = (unsigned char *)malloc(bufsiz + OS_PAGE_SIZE);
- repl_filter_buff = (unsigned char *)ROUND_UP2((unsigned long)filterbuff, OS_PAGE_SIZE);
- if (NULL != free_filter_buff)
+ repl_filter_buff = (unsigned char *)malloc(bufsiz);
+ if (NULL != old_filter_buff)
{
assert(NULL != old_filter_buff);
memcpy(repl_filter_buff, old_filter_buff, repl_filter_bufsiz);
- free(free_filter_buff);
+ free(old_filter_buff);
}
repl_filter_bufsiz = bufsiz;
}
@@ -271,35 +265,29 @@ int gtmsource_alloc_filter_buff(int bufsiz)
void gtmsource_free_filter_buff(void)
{
- if (NULL != filterbuff)
+ if (NULL != repl_filter_buff)
{
assert(NULL != repl_filter_buff);
- free(filterbuff);
- filterbuff = repl_filter_buff = NULL;
+ free(repl_filter_buff);
+ repl_filter_buff = NULL;
repl_filter_bufsiz = 0;
}
}
int gtmsource_alloc_msgbuff(int maxbuffsize)
-{ /* Allocate message buffer */
-
+{ /* Allocate message buffer */
repl_msg_ptr_t oldmsgp;
- unsigned char *free_msgp;
assert(MIN_REPL_MSGLEN < maxbuffsize);
- maxbuffsize = ROUND_UP2(maxbuffsize, OS_PAGE_SIZE);
- if (maxbuffsize > gtmsource_msgbufsiz || NULL == gtmsource_msgp)
+ if ((maxbuffsize > gtmsource_msgbufsiz) || (NULL == gtmsource_msgp))
{
REPL_DPRINT3("Expanding message buff from %d to %d\n", gtmsource_msgbufsiz, maxbuffsize);
- free_msgp = msgbuff;
oldmsgp = gtmsource_msgp;
- msgbuff = (unsigned char *)malloc(maxbuffsize + OS_PAGE_SIZE);
- gtmsource_msgp = (repl_msg_ptr_t)ROUND_UP2((unsigned long)msgbuff, OS_PAGE_SIZE);
- if (NULL != free_msgp)
- { /* Copy existing data */
- assert(NULL != oldmsgp);
+ gtmsource_msgp = (repl_msg_ptr_t)malloc(maxbuffsize);
+ if (NULL != oldmsgp)
+ { /* Copy existing data */
memcpy((unsigned char *)gtmsource_msgp, (unsigned char *)oldmsgp, gtmsource_msgbufsiz);
- free(free_msgp);
+ free(oldmsgp);
}
gtmsource_msgbufsiz = maxbuffsize;
gtmsource_alloc_filter_buff(gtmsource_msgbufsiz);
@@ -309,11 +297,9 @@ int gtmsource_alloc_msgbuff(int maxbuffsize)
void gtmsource_free_msgbuff(void)
{
- if (NULL != msgbuff)
+ if (NULL != gtmsource_msgp)
{
- assert(NULL != gtmsource_msgp);
- free(msgbuff);
- msgbuff = NULL;
+ free(gtmsource_msgp);
gtmsource_msgp = NULL;
gtmsource_msgbufsiz = 0;
}
diff --git a/sr_vvms/iott_use.c b/sr_vvms/iott_use.c
index 8352e9e..c98b833 100644
--- a/sr_vvms/iott_use.c
+++ b/sr_vvms/iott_use.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2009 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,12 +42,17 @@ LITDEF unsigned char filter_index[27] =
,4, 4, 4
};
-GBLREF bool ctrlc_on;
-GBLREF uint4 std_dev_outofband_msk;
-GBLREF uint4 spc_inp_prc;
+GBLREF boolean_t ctrlc_on;
GBLREF io_pair io_std_device;
+GBLREF uint4 spc_inp_prc, std_dev_outofband_msk;
+
LITREF unsigned char io_params_size[];
+error_def(ERR_DEVPARMNEG);
+error_def(ERR_TTINVFILTER);
+error_def(ERR_TTWIDTHTOOBIG);
+error_def(ERR_TTLENGTHTOOBIG);
+
void iott_use(io_desc *iod, mval *pp)
{
bool flush_input;
@@ -67,11 +72,6 @@ void iott_use(io_desc *iod, mval *pp)
t_cap s_mode;
int p_offset;
- error_def(ERR_DEVPARMNEG);
- error_def(ERR_TTINVFILTER);
- error_def(ERR_TTWIDTHTOOBIG);
- error_def(ERR_TTLENGTHTOOBIG);
-
assert(iod->state == dev_open);
assert(iod->type == tt);
assert(iod->pair.in == iod || iod->pair.out == iod);
@@ -91,7 +91,7 @@ void iott_use(io_desc *iod, mval *pp)
if (status == SS$_NORMAL)
status = stat_blk.status;
if (status != SS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
/* although it is only for safety, the following covers for
read * (iott_rdone) and dm_read use of pasthru et al */
s_mode.ext_cap &= (~TT2$M_PASTHRU);
@@ -146,7 +146,7 @@ void iott_use(io_desc *iod, mval *pp)
if (status == SS$_NORMAL)
status = stat_blk.status;
if (status != SS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
break;
case iop_convert:
@@ -172,14 +172,13 @@ void iott_use(io_desc *iod, mval *pp)
status = smg$get_term_data (&out_ttptr->term_tab_entry,
&req_code, &bufsz, &buflen, buf, args);
if (!(status & 1))
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
status = sys$qiow(EFN$C_ENF, out_ttptr->channel, IO$_WRITEVBLK,
&stat_blk, NULL, 0, buf, buflen, 0, 0, 0, 0);
if (status == SS$_NORMAL)
status = stat_blk.status;
if (status != SS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
-
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
if (d_out->dollar.y > 0)
{
d_out->dollar.y --;
@@ -224,7 +223,7 @@ void iott_use(io_desc *iod, mval *pp)
if (status == SS$_NORMAL)
status = stat_blk.status;
if (status != SS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
break;
case iop_exception:
@@ -237,7 +236,7 @@ void iott_use(io_desc *iod, mval *pp)
tab = pp->str.addr + p_offset + 1;
if ((fil_type = namelook(filter_index, filter_names, tab, len)) < 0)
{
- rts_error(VARLSTCNT(1) ERR_TTINVFILTER);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TTINVFILTER);
return;
}
switch (fil_type)
@@ -262,7 +261,7 @@ void iott_use(io_desc *iod, mval *pp)
case iop_field:
GET_SHORT(field, pp->str.addr + p_offset);
if (field < 0)
- rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG);
if (in_ttptr)
if (field == 0)
in_ttptr->in_buf_sz = TTDEF_BUF_SZ;
@@ -291,9 +290,9 @@ void iott_use(io_desc *iod, mval *pp)
case iop_length:
GET_LONG(length, pp->str.addr + p_offset);
if (length < 0)
- rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG);
if (length > TTMAX_PG_LENGTH)
- rts_error(VARLSTCNT(1) ERR_TTLENGTHTOOBIG);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TTLENGTHTOOBIG);
s_mode.pg_length = length;
d_out->length = length;
break;
@@ -366,13 +365,13 @@ void iott_use(io_desc *iod, mval *pp)
status = smg$get_term_data (&out_ttptr->term_tab_entry, &req_code,
&bufsz, &buflen, buf, args);
if (!(status & 1))
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
status = sys$qiow(EFN$C_ENF, out_ttptr->channel, IO$_WRITEVBLK,
&stat_blk, NULL, 0, buf, buflen, 0, 0, 0, 0);
if (status == SS$_NORMAL)
status = stat_blk.status;
if (status != SS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
d_out->dollar.y++;
if (d_out->length)
@@ -383,9 +382,9 @@ void iott_use(io_desc *iod, mval *pp)
case iop_width:
GET_LONG(width, pp->str.addr + p_offset);
if (width < 0)
- rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG);
if (width > TTMAX_PG_WIDTH)
- rts_error(VARLSTCNT(1) ERR_TTWIDTHTOOBIG);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TTWIDTHTOOBIG);
if (width == 0)
{
s_mode.term_char &= (~TT$M_WRAP);
@@ -430,13 +429,13 @@ void iott_use(io_desc *iod, mval *pp)
status = smg$get_term_data (&out_ttptr->term_tab_entry,
&req_code, &bufsz, &buflen, buf, args);
if (!(status & 1))
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
status = sys$qiow(EFN$C_ENF, out_ttptr->channel, IO$_WRITEVBLK,
&stat_blk, NULL, 0, buf, buflen, 0, 0, 0, 0);
if (status == SS$_NORMAL)
status = stat_blk.status;
if (status != SS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
break;
case iop_y:
@@ -454,13 +453,13 @@ void iott_use(io_desc *iod, mval *pp)
status = smg$get_term_data (&out_ttptr->term_tab_entry,
&req_code, &bufsz, &buflen, buf, args);
if (!(status & 1))
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
status = sys$qiow(EFN$C_ENF, out_ttptr->channel, IO$_WRITEVBLK,
&stat_blk, NULL, 0, buf, buflen, 0, 0, 0, 0);
if (status == SS$_NORMAL)
status = stat_blk.status;
if (status != SS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
break;
}
@@ -472,7 +471,7 @@ void iott_use(io_desc *iod, mval *pp)
if (status == SS$_NORMAL)
status = stat_blk.status;
if (status != SS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
if (in_ttptr)
{
in_ttptr->item_list[0].addr = mask_in;
@@ -487,7 +486,7 @@ void iott_use(io_desc *iod, mval *pp)
if (status == SS$_NORMAL)
status = stat_blk.status;
if ((status != SS$_NORMAL) && (status != SS$_TIMEOUT))
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
}
}
diff --git a/sr_vvms/ious_iocontrol.c b/sr_vvms/ious_iocontrol.c
index 2abbafc..85c0d0d 100644
--- a/sr_vvms/ious_iocontrol.c
+++ b/sr_vvms/ious_iocontrol.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2004 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -16,16 +16,16 @@
GBLREF io_pair io_curr_device;
-void ious_iocontrol(mstr *d)
+void ious_iocontrol(mstr *mn, int4 argcnt, va_list args)
{
struct dsc$descriptor val;
- val.dsc$w_length = d->len;
+ val.dsc$w_length = mn->len;
val.dsc$b_dtype = DSC$K_DTYPE_T;
val.dsc$b_class = DSC$K_CLASS_S;
- val.dsc$a_pointer = d->addr;
+ val.dsc$a_pointer = mn->addr;
- (((d_us_struct*)(io_curr_device.out->dev_sp))->disp->iocontrol)(&val);
+ (((d_us_struct*)(io_curr_device.out->dev_sp))->disp->iocontrol)(&val, 0, NULL);
return;
}
diff --git a/sr_vvms/jnl_file_open.c b/sr_vvms/jnl_file_open.c
index 3fd18a8..79b9b96 100644
--- a/sr_vvms/jnl_file_open.c
+++ b/sr_vvms/jnl_file_open.c
@@ -1,6 +1,6 @@
/***************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -144,8 +144,7 @@ uint4 jnl_file_open(gd_region *reg, bool init, void oper_ast())
boolean_t retry;
$DESCRIPTOR(desc, name_buffer);
- if ((dba_bg != reg->dyn.addr->acc_meth) && (dba_mm != reg->dyn.addr->acc_meth))
- GTMASSERT;
+ assertpro((dba_bg == reg->dyn.addr->acc_meth) || (dba_mm == reg->dyn.addr->acc_meth));
if (NULL == oper_ast)
oper_ast = jnl_oper_krnl_ast;
csa = &FILE_INFO(reg)->s_addrs;
@@ -184,7 +183,7 @@ uint4 jnl_file_open(gd_region *reg, bool init, void oper_ast())
fab.fab$l_nam = &nam;
if (init)
{
- cre_jnl_file_intrpt_rename(((int)csd->jnl_file_len), csd->jnl_file_name);
+ cre_jnl_file_intrpt_rename(csa);
nam.nam$l_esa = es_buffer; /* Though conclealed name is not possible, we use it */
nam.nam$b_ess = SIZEOF(es_buffer);
fab.fab$l_fna = csd->jnl_file_name;
diff --git a/sr_vvms/lke.c b/sr_vvms/lke.c
index 32da79f..fb87a5b 100644
--- a/sr_vvms/lke.c
+++ b/sr_vvms/lke.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -43,15 +43,13 @@
#include "util.h"
#include "lke.h"
#include "getjobname.h"
-#include "getjobnum.h"
#include "generic_exit_handler.h"
#include "ladef.h"
#include "ast_init.h"
-#include "get_page_size.h"
#include "init_secshr_addrs.h"
#include "gtm_env_init.h" /* for gtm_env_init() prototype */
#include "patcode.h"
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
GBLREF desblk exi_blk;
@@ -59,8 +57,6 @@ GBLREF int4 lkid;
GBLREF int4 exi_condition;
GBLREF spdesc rts_stringpool, stringpool;
-OS_PAGE_SIZE_DECLARE
-
extern int lke_cmd();
extern int CLI$DCL_PARSE();
extern int CLI$DISPATCH();
@@ -79,15 +75,14 @@ void lke(void)
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- gtm_imagetype_init(LKE_IMAGE);
+ common_startup_init(LKE_IMAGE);
gtm_env_init(); /* read in all environment variables */
util_out_open(0);
SET_EXIT_HANDLER(exi_blk, generic_exit_handler, exi_condition); /* Establish exit handler */
ESTABLISH(util_base_ch);
status =lp_id(&lkid);
if (SS$_NORMAL != status)
- rts_error(VARLSTCNT(1) status);
- get_page_size();
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
stp_init(STP_INITSIZE);
rts_stringpool = stringpool;
getjobname();
@@ -96,7 +91,6 @@ void lke(void)
initialize_pattern_table();
gvinit();
region_init(TRUE);
- getjobnum();
status = lib$get_foreign(&command, 0, &len, 0);
if ((status & 1) && len > 0)
{
diff --git a/sr_vvms/mu_extract.c b/sr_vvms/mu_extract.c
index fbb21f9..03545c5 100644
--- a/sr_vvms/mu_extract.c
+++ b/sr_vvms/mu_extract.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -383,6 +383,6 @@ void mu_extract(void)
mupip_exit(ERR_MUNOFINISH);
}
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_RECORDSTAT, 6, LEN_AND_LIT("TOTAL"),
- grand_total.recknt, grand_total.keylen, grand_total.datalen, grand_total.reclen);
+ &grand_total.recknt, grand_total.keylen, grand_total.datalen, grand_total.reclen);
mupip_exit(success ? SS$_NORMAL : ERR_MUNOFINISH);
}
diff --git a/sr_vvms/mubgetfil.c b/sr_vvms/mubgetfil.c
index c2acdeb..263895f 100644
--- a/sr_vvms/mubgetfil.c
+++ b/sr_vvms/mubgetfil.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,65 +40,59 @@
#include "mupipbckup.h"
#include "gtm_caseconv.h"
-GBLDEF mstr directory;
-GBLDEF bool is_directory;
+GBLDEF mstr directory;
+GBLDEF boolean_t is_directory;
-bool mubgetfil(backup_reg_list *list, char *name, unsigned short len)
+boolean_t mubgetfil(backup_reg_list *list, char *name, unsigned short len)
{
+ char tcp[5];
mstr *mubchkfs(), *temp, file;
uint4 status;
- char tcp[5];
-
- if (0 == len)
- return FALSE;
-
- if ('|' == *name)
- {
- len -= 1;
- list->backup_to = backup_to_exec;
- list->backup_file.len = len;
- list->backup_file.addr = (char *)malloc(len + 1);
- memcpy(list->backup_file.addr, name + 1, len);
- return TRUE;
- }
-
- if (len > 5)
- {
- lower_to_upper(tcp, name, 5);
- if (0 == memcmp(tcp, "TCP:/", 5))
- {
- list->backup_to = backup_to_tcp;
- len -= 5;
- name += 5;
- while ('/' == *name)
- {
- len--;
- name++;
- }
- list->backup_file.len = len;
- list->backup_file.addr = (char *)malloc(len + 1);
- memcpy(list->backup_file.addr, name, len);
- *(list->backup_file.addr + len) = 0;
- return TRUE;
- }
- }
+ if (0 == len)
+ return FALSE;
+ if ('|' == *name)
+ {
+ len -= 1;
+ list->backup_to = backup_to_exec;
+ list->backup_file.len = len;
+ list->backup_file.addr = (char *)malloc(len + 1);
+ memcpy(list->backup_file.addr, name + 1, len);
+ return TRUE;
+ }
+ if (len > 5)
+ {
+ lower_to_upper(tcp, name, 5);
+ if (0 == memcmp(tcp, "TCP:/", 5))
+ {
+ list->backup_to = backup_to_tcp;
+ len -= 5;
+ name += 5;
+ while ('/' == *name)
+ {
+ len--;
+ name++;
+ }
+ list->backup_file.len = len;
+ list->backup_file.addr = (char *)malloc(len + 1);
+ memcpy(list->backup_file.addr, name, len);
+ *(list->backup_file.addr + len) = 0;
+ return TRUE;
+ }
+ }
file.addr = name;
file.len = len;
if (NULL == (temp = mubchkfs(&file))) /* mubchkfs is responsible for error message if NULL, and allocate space otherwise */
return FALSE;
-
if (']' == *(temp->addr + temp->len - 1))
{
is_directory = TRUE;
directory = *temp;
mubexpfilnam(list);
- }
- else
+ } else
{
is_directory = FALSE;
list->backup_file = *temp;
}
-
return TRUE;
}
diff --git a/sr_vvms/mupip.c b/sr_vvms/mupip.c
index 42e3075..a5c33e1 100644
--- a/sr_vvms/mupip.c
+++ b/sr_vvms/mupip.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -40,15 +40,13 @@
#include "util.h"
#include "mupip_exit.h"
#include "lmdef.h"
-#include "getjobnum.h"
#include "patcode.h"
#include "generic_exit_handler.h"
#include "ast_init.h"
-#include "get_page_size.h"
#include "init_secshr_addrs.h"
#include "mupip_getcmd.h"
#include "gtm_env_init.h" /* for gtm_env_init() prototype */
-#include "gtm_imagetype_init.h"
+#include "common_startup_init.h"
#include "gtm_threadgbl_init.h"
GBLREF desblk exi_blk;
@@ -62,8 +60,6 @@ error_def (ERR_WILLEXPIRE);
error_def (LP_NOCNFDB);
error_def (LP_INVCSM);
-OS_PAGE_SIZE_DECLARE
-
LITREF char gtm_product[PROD];
LITREF int4 gtm_product_len;
LITREF char gtm_version[VERS];
@@ -84,7 +80,7 @@ mupip()
DCL_THREADGBL_ACCESS;
GTM_THREADGBL_INIT;
- gtm_imagetype_init(MUPIP_IMAGE);
+ common_startup_init(MUPIP_IMAGE);
gtm_env_init(); /* read in all environment variables */
licensed = TRUE;
TREF(transform) = TRUE;
@@ -92,8 +88,6 @@ mupip()
util_out_open(0);
SET_EXIT_HANDLER(exi_blk, generic_exit_handler, exi_condition); /* Establish exit handler */
ESTABLISH(util_base_ch);
- get_page_size();
- getjobnum();
INVOKE_INIT_SECSHR_ADDRS;
# ifdef NOLICENSE
status = SS$_NORMAL;
diff --git a/sr_vvms/op_fnzsearch.c b/sr_vvms/op_fnzsearch.c
index db11fd5..88cacb1 100644
--- a/sr_vvms/op_fnzsearch.c
+++ b/sr_vvms/op_fnzsearch.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2011 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -12,13 +12,13 @@
#include "mdef.h"
#include "gtm_string.h"
-
#include <rms.h>
#include <ssdef.h>
+
#include "stringpool.h"
#include "op.h"
+#include "op_fnzsearch.h"
-#define MAX_STRM_CT 256
typedef struct fnzsearch
{ short index;
@@ -37,7 +37,7 @@ GBLREF spdesc stringpool;
error_def(ERR_ZFILENMTOOLONG);
error_def(ERR_ZSRCHSTRMCT);
-int op_fnzsearch(mval *file,mint strm,mval *ret)
+int op_fnzsearch(mval *file, mint strm, mint mcmd, mval *ret)
{
search_struct *sea_ptr,*sea,*ptr;
unsigned char esa[MAX_FN_LEN];
@@ -64,11 +64,11 @@ int op_fnzsearch(mval *file,mint strm,mval *ret)
}
assert(fab_sea != 0);
index = (short)strm;
- if (index > MAX_STRM_CT || index < 0)
- rts_error(VARLSTCNT(1) ERR_ZSRCHSTRMCT);
+ if (mcmd && ((MAX_STRM_CT < index) || ( 0 > index))) /* Bypass stream check for internal uses */
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZSRCHSTRMCT);
MV_FORCE_STR(file);
if (file->str.len > MAX_FN_LEN)
- rts_error(VARLSTCNT(4) ERR_ZFILENMTOOLONG,2,file->str.len,file->str.addr);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZFILENMTOOLONG, 2, file->str.len, file->str.addr);
sea_ptr = fab_sea;
while(sea_ptr->next != 0 && sea_ptr->next->index <= index)
sea_ptr = sea_ptr->next;
@@ -91,7 +91,7 @@ int op_fnzsearch(mval *file,mint strm,mval *ret)
sea_ptr =sea_ptr->next;
memcpy(sea_ptr->fab.fab$l_fna,file->str.addr,file->str.len);
if ((status = sys$parse(&(sea_ptr->fab),0,0)) != RMS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
} else
{
if (file->str.len > sea_ptr->fab.fab$b_fns)
@@ -104,7 +104,7 @@ int op_fnzsearch(mval *file,mint strm,mval *ret)
memcpy(sea_ptr->fab.fab$l_fna,file->str.addr,file->str.len);
sea_ptr->fab.fab$b_fns = file->str.len;
if ((status = sys$parse(&(sea_ptr->fab),0,0)) != RMS$_NORMAL)
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
}
status = sys$search(&(sea_ptr->fab), 0, 0);
@@ -138,7 +138,7 @@ int op_fnzsearch(mval *file,mint strm,mval *ret)
sea_ptr->fab.fab$b_fns = 0;
break;
default:
- rts_error(VARLSTCNT(1) status );
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
ret->mvtype = MV_STR;
return 0; /* dummy for compatibility with unix prototype */
diff --git a/sr_vvms/op_zmess.c b/sr_vvms/op_zmess.c
index f29e6fd..bf74b58 100644
--- a/sr_vvms/op_zmess.c
+++ b/sr_vvms/op_zmess.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2010 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,8 +18,10 @@
#include "op.h"
#include "tp_restart.h"
-#define FAO_BUFFER_SPACE 2048
-#define MAX_MSG_SIZE 256
+#define FAO_BUFFER_SPACE 2048
+#define MAX_MSG_SIZE 256
+
+error_def(ERR_TPRETRY);
void op_zmess(int4 errnum, ...)
{
@@ -29,14 +31,13 @@ void op_zmess(int4 errnum, ...)
unsigned char faostat[4];
unsigned char msgbuff[MAX_MSG_SIZE + 1];
unsigned char buff[FAO_BUFFER_SPACE];
- int4 fao[MAX_FAO_PARMS + 1];
+ int4 fao[MAX_FAO_PARMS];
$DESCRIPTOR(d_sp, msgbuff);
- error_def(ERR_TPRETRY);
-
VAR_START(var, errnum);
va_count(cnt);
cnt--;
+ assert(34 == MAX_FAO_PARMS); /* Defined in fao_parm.h. */
status = sys$getmsg(errnum, &m_len, &d_sp, 0, &faostat[0]);
if ((status & 1) && m_len)
{
@@ -49,23 +50,19 @@ void op_zmess(int4 errnum, ...)
va_end(var);
if (faocnt != -1)
{
- /* Currently there are a max of 20 fao parms (MAX_FAO_PARMS) allowed, hence passing upto fao_list[19].
- * An assert is added to ensure this code is changed whenever the macro MAX_FAO_PARMS is changed.
- * The # of arguments passed below should change accordingly.
- */
- assert(MAX_FAO_PARMS == 20);
if (ERR_TPRETRY == errnum)
{ /* A TP restart is being signalled. Set t_fail_hist just like a TRESTART command would */
op_trestart_set_cdb_code();
}
- rts_error(VARLSTCNT(MAX_FAO_PARMS + 2) errnum, faocnt, fao[0], fao[1], fao[2], fao[3], fao[4], fao[5],
- fao[6], fao[7], fao[8], fao[9], fao[10], fao[11], fao[12], fao[13], fao[14], fao[15], fao[16],
- fao[17], fao[18], fao[19]);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(MAX_FAO_PARMS + 2) errnum, faocnt, fao[0], fao[1], fao[2], fao[3],
+ fao[4], fao[5], fao[6], fao[7], fao[8], fao[9], fao[10], fao[11], fao[12], fao[13], fao[14],
+ fao[15], fao[16], fao[17], fao[18], fao[19], fao[20], fao[21], fao[22], fao[23], fao[24], fao[25],
+ fao[26], fao[27], fao[28], fao[29], fao[30], fao[31], fao[32], fao[33]);
}
return;
} else
{
va_end(var);
- rts_error(VARLSTCNT(1) status);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
}
}
diff --git a/sr_vvms/rtnhdr.h b/sr_vvms/rtnhdr.h
index 427bf14..3bb5525 100644
--- a/sr_vvms/rtnhdr.h
+++ b/sr_vvms/rtnhdr.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -151,5 +151,6 @@ lnr_tabent *op_labaddr(rhdtyp *routine, mval *label, int4 offset);
void urx_resolve(rhdtyp *rtn, lab_tabent *lbl_tab, lab_tabent *lbl_top);
char *rtnlaboff2entryref(char *entryref_buff, mident *rtn, mident *lab, int offset);
void rtn_tbl_sort(rtn_tabent *base, rtn_tabent *end);
+boolean_t on_stack(rhdtyp *rtnhdr, boolean_t *need_duplicate);
#endif /* RTNHDR_H_INCLUDED */
diff --git a/sr_vvms/send_msg.c b/sr_vvms/send_msg.c
index b5b21f8..49c145b 100644
--- a/sr_vvms/send_msg.c
+++ b/sr_vvms/send_msg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -87,15 +87,16 @@ void send_msg(int msg_id_arg, ...)
--arg_count;
}
- /* Currently there are a max of 20 fao parms (MAX_FAO_PARMS) allowed, hence passing upto fao_list[19].
+ /* Currently there are a max of 34 fao parms (MAX_FAO_PARMS) allowed, hence passing upto fao_list[33].
* An assert is added to ensure this code is changed whenever the macro MAX_FAO_PARMS is changed.
* The # of arguments passed below should change accordingly.
*/
- assert(MAX_FAO_PARMS == 20);
+ assert(MAX_FAO_PARMS == 34);
util_out_print(msg_string.addr, NOFLUSH, fao_list[0], fao_list[1], fao_list[2], fao_list[3], fao_list[4],
- fao_list[5], fao_list[6], fao_list[7], fao_list[8], fao_list[9], fao_list[10], fao_list[11],
- fao_list[12], fao_list[13], fao_list[14], fao_list[15], fao_list[16], fao_list[17],
- fao_list[18], fao_list[19]);
+ fao_list[5], fao_list[6], fao_list[7], fao_list[8], fao_list[9], fao_list[10], fao_list[11], fao_list[12],
+ fao_list[13], fao_list[14], fao_list[15], fao_list[16], fao_list[17], fao_list[18], fao_list[19],
+ fao_list[20], fao_list[21], fao_list[22], fao_list[23], fao_list[24], fao_list[25], fao_list[26],
+ fao_list[27], fao_list[28], fao_list[29], fao_list[30], fao_list[31], fao_list[32], fao_list[33]);
if (arg_count < 1)
{
diff --git a/sr_vvms/sgtm_putmsg.c b/sr_vvms/sgtm_putmsg.c
index f0b31ae..08bcdf0 100644
--- a/sr_vvms/sgtm_putmsg.c
+++ b/sr_vvms/sgtm_putmsg.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2012 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -84,15 +84,16 @@ void sgtm_putmsg(char *out_str, ...)
--arg_count;
}
- /* Currently there are a max of 20 fao parms (MAX_FAO_PARMS) allowed, hence passing upto fao_list[19].
+ /* Currently there are a max of 34 fao parms (MAX_FAO_PARMS) allowed, hence passing upto fao_list[33].
* An assert is added to ensure this code is changed whenever the macro MAX_FAO_PARMS is changed.
* The # of arguments passed below should change accordingly.
*/
- assert(MAX_FAO_PARMS == 20);
+ assert(MAX_FAO_PARMS == 34);
util_out_print(msg_string.addr, NOFLUSH, fao_list[0], fao_list[1], fao_list[2], fao_list[3], fao_list[4],
- fao_list[5], fao_list[6], fao_list[7], fao_list[8], fao_list[9], fao_list[10], fao_list[11],
- fao_list[12], fao_list[13], fao_list[14], fao_list[15], fao_list[16], fao_list[17],
- fao_list[18], fao_list[19]);
+ fao_list[5], fao_list[6], fao_list[7], fao_list[8], fao_list[9], fao_list[10], fao_list[11], fao_list[12],
+ fao_list[13], fao_list[14], fao_list[15], fao_list[16], fao_list[17], fao_list[18], fao_list[19],
+ fao_list[20], fao_list[21], fao_list[22], fao_list[23], fao_list[24], fao_list[25], fao_list[26],
+ fao_list[27], fao_list[28], fao_list[29], fao_list[30], fao_list[31], fao_list[32], fao_list[33]);
if (arg_count < 1)
break;
diff --git a/sr_vvms/spkitbld.m b/sr_vvms/spkitbld.m
index b4aac7d..6f7ca7f 100644
--- a/sr_vvms/spkitbld.m
+++ b/sr_vvms/spkitbld.m
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2001, 2003 Sanchez Computer Associates, Inc. ;
+; Copyright 2001, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -19,18 +19,24 @@ spkitbld ; ; ; edit the gtm$vrt:[t%%]*_spkitbld.dat version
Set gtmvrt=$Piece(gtmvrt,"]")
Set newver=$$FUNC^%ucase($Piece(gtmvrt,".",2))
If newver'?1"V"2N.2A1.3N.1A Write !,"Invalid version designation" Quit
+ Write "Fixing the version in packaging config files to ",newver,!
Set newver=$Extract(newver,2,9999)
For tv="BL","FT" If newver[tv Set newver=$Piece(newver,tv)_$Select(tv="BL":88,1:99)_$Piece(newver,tv,2)
If newver?.N1.A For i=$Length(newver):-1:2 Set newver=$Extract(newver,1,i-1)_($Ascii(newver,i)#10)_$Extract(newver,i+1,9999)
Set file=$ZSEARCH("foo.bar") ;clear any current search
For Set file=$Piece($ZSEARCH(mask),";") Quit:'$l(file) Do
+ . Use $principal
+ . Write "Opening file ",file,!
. Open file:(readonly:exception="Goto eof"),temp:newversion
. Use file
. Read line
+ . Use $principal
+ . Write "Old version: ",line,!
. Set oldver=$Piece(line," ",3)
. For i=1:1:$l(oldver) Quit:$Extract(oldver,i)?1N
. Set prod=$Extract(oldver,1,i-1)
. Set $Piece(line," ",3)=prod_newver
+ . Write "New version: ",line,!,!
. Use temp
. Write line,!
. For Use file Read line Use temp Write line,!
diff --git a/sr_vvms/spkitupdate.com b/sr_vvms/spkitupdate.com
index e64a338..bd734bb 100644
--- a/sr_vvms/spkitupdate.com
+++ b/sr_vvms/spkitupdate.com
@@ -1,6 +1,6 @@
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$! !
-$! Copyright 2001, 2013 Fidelity Information Services Inc !
+$! Copyright 2001, 2014 Fidelity Information Services Inc !
$! !
$! This source code contains the intellectual property !
$! of its copyright holder(s), and is made available !
@@ -14,12 +14,13 @@ $!
$ vno = p1
$ p1 = ""
$ say = "write sys$output"
-$ gawk:=$gtm_bin:gawk.exe
+$ gawk:=$gtm$bin:gawk.exe
$ say "Fixing the version in packaging config files to "'vno'
$ ver 'vno' p
$ curr_priv = f$setprv("sysprv")
$ gtma := $ gtm$exe:gtm$dmod.exe
$ gtma "user:[library.''vno']"
+set $zro=$piece($zroutines,"=(",1)_"=(gtm$vrt:[src],"_$piece($zroutines,"=(",2)
d ^spkitbld
$ curr_priv=f$setprv(curr_priv)
$ delete/nolog/since spkitbld.obj.,_ucase.obj.
diff --git a/sr_vvms/term_setup.c b/sr_vvms/term_setup.c
index d1bfe98..97db7b9 100644
--- a/sr_vvms/term_setup.c
+++ b/sr_vvms/term_setup.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001 Sanchez Computer Associates, Inc. *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -18,28 +18,26 @@
#include "outofband.h"
#include "term_setup.h"
-GBLREF int4 outofband; /* enumerated:ctrap,ctrlc or ctrly */
-GBLREF int4 std_dev_outofband_msk;
-GBLREF io_pair io_std_device; /* standard device */
+GBLDEF boolean_t ctrlc_on; /* TRUE in cenable mode; FALSE in nocenable mode */
-GBLDEF bool ctrlc_on; /* whether ctrlc trap enabled */
-
-void term_setup(bool ctrlc_enable)
+GBLREF int4 outofband; /* enumerated: ctrap,ctrlc or ctrly */
+GBLREF int4 std_dev_outofband_msk;
+GBLREF io_pair io_std_device; /* standard device */
+void term_setup(boolean_t ctrlc_enable)
{
- uint4 status;
- io_terminator outofbands;
+ io_terminator outofbands;
+ uint4 status;
status = sys$clref(efn_outofband);
assert(status == SS$_WASSET || status == SS$_WASCLR);
outofband = 0;
-
if (io_std_device.in->type == tt)
{
ctrlc_on = ctrlc_enable ;
if (ctrlc_on)
std_dev_outofband_msk |= CTRLC_MSK;
iott_resetast(io_std_device.in);
- }else
+ } else
ctrlc_on = FALSE;
}
diff --git a/sr_vvms/ttt.c b/sr_vvms/ttt.c
index e08ca54..eb24019 100644
--- a/sr_vvms/ttt.c
+++ b/sr_vvms/ttt.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,683 +13,687 @@
#include "vxi.h"
#include "vxt.h"
#include "xfer_enum.h"
-LITDEF short ttt[4220] = {
+LITDEF short ttt[4240] = {
-/* 0 */ 0,0,0,0,325,3477,2931,569,
-/* 8 */ 2309,2916,2946,1981,421,3427,2102,3049,
-/* 16 */ 2185,2173,3660,3697,2146,2155,2227,2167,
-/* 24 */ 2218,2197,2125,789,804,816,828,867,
-/* 32 */ 885,906,935,965,980,995,1013,3034,
-/* 40 */ 1085,1118,1154,1220,1271,1568,1601,1616,
-/* 48 */ 1646,1712,1742,1766,1829,1850,1865,3492,
-/* 56 */ 3514,0,0,0,0,584,0,525,
-/* 64 */ 0,1967,0,3020,0,0,0,0,
-/* 72 */ 0,0,357,433,2287,2293,2708,2735,
-/* 80 */ 2753,2856,2794,2785,2871,3566,3650,2967,
-/* 88 */ 0,2999,3115,3078,3063,3093,3441,3291,
-/* 96 */ 3572,3584,3599,3623,3632,3617,3608,3326,
-/* 104 */ 3693,3706,3728,3765,3777,3798,3822,3888,
-/* 112 */ 0,0,2904,2269,3167,4169,663,4172,
-/* 120 */ 717,2765,3133,539,545,4175,2372,2459,
-/* 128 */ 2359,492,2395,2479,2134,2417,2489,4178,
-/* 136 */ 2254,2245,4182,1289,4183,353,349,3315,
-/* 144 */ 445,4187,4190,4193,2985,4196,4199,4202,
-/* 152 */ 4205,4208,4211,3463,0,2880,2548,2526,
-/* 160 */ 1529,2517,2305,2116,2831,2002,742,2821,
-/* 168 */ 0,0,2324,3641,3669,1493,3593,2407,
-/* 176 */ 1995,554,3789,1814,2236,1205,340,3119,
-/* 184 */ 626,695,607,673,3753,1133,3721,2960,
-/* 192 */ 2263,2895,2974,645,1025,2835,4214,2469,
-/* 200 */ 3840,3858,3873,516,2850,3111,1928,3909,
-/* 208 */ 3900,1307,3455,598,1631,1700,2432,4217,
-/* 216 */ 3526,2505,751,846,3150,3681,3550,3536,
-/* 224 */ 3543,3532,727,920,2382,1067,2346,1055,
-/* 232 */ 2206,1040,1100,2444,1463,1406,1391,1445,
-/* 240 */ 1361,1373,1418,1346,1430,1478,772,3413,
-/* 248 */ 0,944,953,3270,1841,3249,2333,3945,
-/* 256 */ 3915,3921,3933,3955,1244,1256,1178,1190,
-/* 264 */ 1232,3504,1676,1913,0,1319,1505,1550,
-/* 272 */ 3347,1583,1661,1688,1799,1778,3389,1724,
-/* 280 */ 3368,1895,0,0,1955,3978,1877,3177,
-/* 288 */ 3189,3201,3213,2744,2759,1517,456,1334,
-/* 296 */ 0,654,3225,3237,0,3969,0,0,
-/* 304 */ 0,0,3744,3990,4001,4013,4022,4036,
-/* 312 */ 4049,4059,4076,4088,4097,4109,4121,4133,
-/* 320 */ 4148,4160,0,0,0,VXI_PUSHAB,VXT_VAL,0,
-/* 328 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 336 */ 3,VXT_XFER,SIZEOF(char *) * (short int)xf_add,VXT_END,
-/* 340 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_bindparm,
-/* 348 */ VXT_END,
-/* 349 */ VXI_INCL,VXT_VAL,1,VXT_END,
-/* 353 */ VXI_CLRL,VXT_VAL,0,VXT_END,
-/* 357 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_break,VXT_END,
-/* 361 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callb,VXI_BRB,VXT_JMP,
-/* 369 */ 1,VXT_END,
-/* 371 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_calll,VXI_JMP,VXT_JMP,
-/* 379 */ 1,VXT_END,
-/* 381 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callw,VXI_BRW,VXT_JMP,
-/* 389 */ 1,VXT_END,
-/* 391 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspb,VXI_BRB,VXT_JMP,
-/* 399 */ 1,VXT_END,
-/* 401 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspl,VXI_JMP,VXT_JMP,
-/* 409 */ 1,VXT_END,
-/* 411 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspw,VXI_BRW,VXT_JMP,
-/* 419 */ 1,VXT_END,
-/* 421 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 429 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_cat,VXT_END,
-/* 433 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 441 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_close,VXT_END,
-/* 445 */ VXI_BICB2,VXT_LIT,1,VXT_REG,0x5A,VXI_CALLS,VXT_LIT,0,
-/* 453 */ VXT_XFER,SIZEOF(char *) * (short int)xf_dt_false,VXT_END,
-/* 456 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_clralsvars,
-/* 464 */ VXT_END,
-/* 465 */ VXI_TSTL,VXT_VAL,1,VXT_END,
-/* 469 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2bool,
-/* 477 */ VXT_END,
-/* 478 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2mint,
-/* 486 */ VXI_MOVL,VXT_REG,0x50,VXT_VAL,0,VXT_END,
-/* 492 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 500 */ SIZEOF(char *) * (short int)xf_commarg,VXT_END,
-/* 502 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVL,VXT_VAL,1,
-/* 510 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mint2mval,VXT_END,
-/* 516 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2num,
-/* 524 */ VXT_END,
-/* 525 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 533 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_contain,VXT_END,
-/* 539 */ VXI_MOVL,VXT_REG,0x6C,VXT_ADDR,0,VXT_END,
-/* 545 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_currtn,
-/* 553 */ VXT_END,
-/* 554 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 562 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_cvtparm,VXT_END,
-/* 569 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 577 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_div,VXT_END,
-/* 584 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
-/* 592 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equ,VXT_END,
-/* 598 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equnul,
-/* 606 */ VXT_END,
-/* 607 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 615 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_LIT,0,VXI_JSB,
-/* 623 */ VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
-/* 626 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 634 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_JSB,
-/* 642 */ VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
-/* 645 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunret,
-/* 653 */ VXT_END,
-/* 654 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunretals,
-/* 662 */ VXT_END,
-/* 663 */ VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,VXT_GREF,1,VXI_JSB,VXT_XFER,
-/* 671 */ SIZEOF(char *) * (short int)xf_extcall,VXT_END,
-/* 673 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 681 */ 3,VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,
-/* 689 */ VXT_GREF,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
-/* 695 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 703 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,
-/* 711 */ VXT_GREF,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
-/* 717 */ VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,VXT_GREF,1,VXI_JSB,VXT_XFER,
-/* 725 */ SIZEOF(char *) * (short int)xf_extjmp,VXT_END,
-/* 727 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 735 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_exp,VXT_END,
-/* 742 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fetch,
-/* 750 */ VXT_END,
-/* 751 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 759 */ 3,VXI_PUSHAB,VXT_GREF,2,VXI_PUSHL,VXT_LIT,0,VXI_CALLS,
-/* 767 */ VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
-/* 772 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 780 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fgnlookup,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 788 */ VXT_END,
-/* 789 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 797 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnascii,VXT_END,
-/* 804 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 812 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnchar,VXT_END,
-/* 816 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 824 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fndata,VXT_END,
-/* 828 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 836 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 844 */ SIZEOF(char *) * (short int)xf_fnextract,VXT_END,
-/* 846 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 854 */ 3,VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,
-/* 862 */ VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
-/* 867 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 875 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 883 */ SIZEOF(char *) * (short int)xf_fnfind,VXT_END,
-/* 885 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 893 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 901 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfnumber,VXT_END,
-/* 906 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
-/* 914 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget,VXT_END,
-/* 920 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 928 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget2,VXT_END,
-/* 935 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget,
-/* 943 */ VXT_END,
-/* 944 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget1,
-/* 952 */ VXT_END,
-/* 953 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 961 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget1,VXT_END,
-/* 965 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 973 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnincr,VXT_END,
-/* 980 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 988 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnj2,VXT_END,
-/* 995 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1003 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1011 */ SIZEOF(char *) * (short int)xf_fnj3,VXT_END,
-/* 1013 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1021 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlength,VXT_END,
-/* 1025 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1033 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvname,VXT_END,
-/* 1040 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
-/* 1048 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvnameo2,VXT_END,
-/* 1055 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1063 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvprvname,VXT_END,
-/* 1067 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 1075 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,2,VXT_XFER,
-/* 1083 */ SIZEOF(char *) * (short int)xf_fnname,VXT_END,
-/* 1085 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1093 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnnext,VXT_END,
-/* 1100 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
-/* 1108 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1116 */ SIZEOF(char *) * (short int)xf_fno2,VXT_END,
-/* 1118 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1126 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnorder,VXT_END,
-/* 1133 */ VXI_PUSHL,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,
-/* 1141 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1149 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnp1,VXT_END,
-/* 1154 */ VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,
-/* 1162 */ 4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 1170 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpiece,VXT_END,
-/* 1178 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1186 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqlength,VXT_END,
-/* 1190 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1198 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqsubscript,VXT_END,
-/* 1205 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1213 */ 0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnquery,VXT_END,
-/* 1220 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1228 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnrandom,VXT_END,
-/* 1232 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1240 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnreverse,VXT_END,
-/* 1244 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1252 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack1,VXT_END,
-/* 1256 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1264 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack2,VXT_END,
-/* 1271 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1279 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1287 */ SIZEOF(char *) * (short int)xf_fntext,VXT_END,
-/* 1289 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1297 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1305 */ SIZEOF(char *) * (short int)xf_fntranslate,VXT_END,
-/* 1307 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 1315 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnview,VXT_END,
-/* 1319 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 1327 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzascii,VXT_END,
-/* 1334 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1342 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzahandle,VXT_END,
-/* 1346 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1354 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitand,VXT_END,
-/* 1361 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1369 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitcoun,VXT_END,
-/* 1373 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1381 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1389 */ SIZEOF(char *) * (short int)xf_fnzbitfind,VXT_END,
-/* 1391 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1399 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitget,VXT_END,
-/* 1406 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1414 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitlen,VXT_END,
-/* 1418 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1426 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitnot,VXT_END,
-/* 1430 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1438 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitor,VXT_END,
-/* 1445 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1453 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1461 */ SIZEOF(char *) * (short int)xf_fnzbitset,VXT_END,
-/* 1463 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1471 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitstr,VXT_END,
-/* 1478 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1486 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitxor,VXT_END,
-/* 1493 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 1501 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzcall,VXT_END,
-/* 1505 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 1513 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzchar,VXT_END,
-/* 1517 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1525 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdata,VXT_END,
-/* 1529 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
-/* 1537 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1545 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdate,VXT_END,
-/* 1550 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 1558 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1566 */ SIZEOF(char *) * (short int)xf_fnzextract,VXT_END,
-/* 1568 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1576 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzfile,VXT_END,
-/* 1583 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1591 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1599 */ SIZEOF(char *) * (short int)xf_fnzfind,VXT_END,
-/* 1601 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1609 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetdvi,VXT_END,
-/* 1616 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1624 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetjpi,VXT_END,
-/* 1631 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1639 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetlki,VXT_END,
-/* 1646 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1654 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetsyi,VXT_END,
-/* 1661 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1669 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzj2,VXT_END,
-/* 1676 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1684 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzjobexam,VXT_END,
-/* 1688 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1696 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlength,VXT_END,
-/* 1700 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1708 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlkid,VXT_END,
-/* 1712 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1720 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzm,VXT_END,
-/* 1724 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1732 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1740 */ SIZEOF(char *) * (short int)xf_fnzp1,VXT_END,
-/* 1742 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
-/* 1750 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 1758 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzparse,VXT_END,
-/* 1766 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1774 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpid,VXT_END,
-/* 1778 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 1786 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1794 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpiece,VXT_END,
-/* 1799 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1807 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpopulation,VXT_END,
-/* 1814 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1822 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzprevious,VXT_END,
-/* 1829 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1837 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpriv,VXT_END,
-/* 1841 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzqgblmod,
-/* 1849 */ VXT_END,
-/* 1850 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1858 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsearch,VXT_END,
-/* 1865 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1873 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsetprv,VXT_END,
-/* 1877 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1885 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1893 */ SIZEOF(char *) * (short int)xf_fnzsubstr,VXT_END,
-/* 1895 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1903 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1911 */ SIZEOF(char *) * (short int)xf_fnztranslate,VXT_END,
-/* 1913 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1921 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsigproc,VXT_END,
-/* 1928 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,6,VXI_PUSHAB,VXT_VAL,
-/* 1936 */ 5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,
-/* 1944 */ VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,7,
-/* 1952 */ VXT_XFER,SIZEOF(char *) * (short int)xf_fnztrnlnm,VXT_END,
-/* 1955 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1963 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwidth,VXT_END,
-/* 1967 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 1975 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_follow,VXT_END,
-/* 1981 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
-/* 1989 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forcenum,VXT_END,
-/* 1995 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forchk1,VXT_END,
-/* 2002 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2010 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forinit,VXT_END,
-/* 2015 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldob,VXI_BRB,VXT_JMP,
-/* 2023 */ 1,VXT_END,
-/* 2025 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldol,VXI_JMP,VXT_JMP,
-/* 2033 */ 1,VXT_END,
-/* 2035 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldow,VXI_BRW,VXT_JMP,
+/* 0 */ 0,0,0,0,330,3497,2951,574,
+/* 8 */ 2329,2936,2966,2001,426,3447,2122,3069,
+/* 16 */ 2205,2193,3680,3717,2166,2175,2247,2187,
+/* 24 */ 2238,2217,2145,794,809,821,833,872,
+/* 32 */ 890,911,940,970,985,1000,1018,3054,
+/* 40 */ 1090,1123,1159,1225,1276,1573,1606,1621,
+/* 48 */ 1651,1717,1747,1771,1834,1855,1873,3512,
+/* 56 */ 3534,0,0,0,0,589,0,530,
+/* 64 */ 0,1987,0,3040,0,0,0,0,
+/* 72 */ 0,0,362,438,2307,2313,2728,2755,
+/* 80 */ 2773,2876,2814,2805,2891,3586,3670,2987,
+/* 88 */ 0,3019,3135,3098,3083,3113,3461,3311,
+/* 96 */ 3592,3604,3619,3643,3652,3637,3628,3346,
+/* 104 */ 3713,3726,3748,3785,3797,3818,3842,3908,
+/* 112 */ 0,0,2924,2289,3187,4189,668,4192,
+/* 120 */ 722,2785,3153,544,550,4195,2392,2479,
+/* 128 */ 2379,497,2415,2499,2154,2437,2509,4198,
+/* 136 */ 2274,2265,4202,1294,4203,358,354,3335,
+/* 144 */ 450,4207,4210,4213,3005,4216,4219,4222,
+/* 152 */ 4225,4228,4231,3483,0,2900,2568,2546,
+/* 160 */ 1534,2537,2325,2136,2851,2022,747,2841,
+/* 168 */ 0,0,2344,3661,3689,1498,3613,2427,
+/* 176 */ 2015,559,3809,1819,2256,1210,345,3139,
+/* 184 */ 631,700,612,678,3773,1138,3741,2980,
+/* 192 */ 2283,2915,2994,650,1030,2855,4234,2489,
+/* 200 */ 3860,3878,3893,521,2870,3131,1948,3929,
+/* 208 */ 3920,1312,3475,603,1636,1705,2452,4237,
+/* 216 */ 3546,2525,756,851,3170,3701,3570,3556,
+/* 224 */ 3563,3552,732,925,2402,1072,2366,1060,
+/* 232 */ 2226,1045,1105,2464,1468,1411,1396,1450,
+/* 240 */ 1366,1378,1423,1351,1435,1483,777,3433,
+/* 248 */ 0,949,958,3290,1846,3269,2353,3965,
+/* 256 */ 3935,3941,3953,3975,1249,1261,1183,1195,
+/* 264 */ 1237,3524,1681,1933,0,1324,1510,1555,
+/* 272 */ 3367,1588,1666,1693,1804,1783,3409,1729,
+/* 280 */ 3388,1915,0,0,1975,3998,1897,3197,
+/* 288 */ 3209,3221,3233,2764,2779,1522,461,1339,
+/* 296 */ 0,659,3245,3257,0,3989,0,0,
+/* 304 */ 0,0,3764,4010,4021,4033,4042,4056,
+/* 312 */ 4069,4079,4096,4108,4117,4129,4141,4153,
+/* 320 */ 4168,4180,0,0,0,1885,0,0,
+/* 328 */ 0,0,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,
+/* 336 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_add,
+/* 344 */ VXT_END,
+/* 345 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_bindparm,
+/* 353 */ VXT_END,
+/* 354 */ VXI_INCL,VXT_VAL,1,VXT_END,
+/* 358 */ VXI_CLRL,VXT_VAL,0,VXT_END,
+/* 362 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_break,VXT_END,
+/* 366 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callb,VXI_BRB,VXT_JMP,
+/* 374 */ 1,VXT_END,
+/* 376 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_calll,VXI_JMP,VXT_JMP,
+/* 384 */ 1,VXT_END,
+/* 386 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callw,VXI_BRW,VXT_JMP,
+/* 394 */ 1,VXT_END,
+/* 396 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspb,VXI_BRB,VXT_JMP,
+/* 404 */ 1,VXT_END,
+/* 406 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspl,VXI_JMP,VXT_JMP,
+/* 414 */ 1,VXT_END,
+/* 416 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspw,VXI_BRW,VXT_JMP,
+/* 424 */ 1,VXT_END,
+/* 426 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 434 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_cat,VXT_END,
+/* 438 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 446 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_close,VXT_END,
+/* 450 */ VXI_BICB2,VXT_LIT,1,VXT_REG,0x5A,VXI_CALLS,VXT_LIT,0,
+/* 458 */ VXT_XFER,SIZEOF(char *) * (short int)xf_dt_false,VXT_END,
+/* 461 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_clralsvars,
+/* 469 */ VXT_END,
+/* 470 */ VXI_TSTL,VXT_VAL,1,VXT_END,
+/* 474 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2bool,
+/* 482 */ VXT_END,
+/* 483 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2mint,
+/* 491 */ VXI_MOVL,VXT_REG,0x50,VXT_VAL,0,VXT_END,
+/* 497 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 505 */ SIZEOF(char *) * (short int)xf_commarg,VXT_END,
+/* 507 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVL,VXT_VAL,1,
+/* 515 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mint2mval,VXT_END,
+/* 521 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2num,
+/* 529 */ VXT_END,
+/* 530 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 538 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_contain,VXT_END,
+/* 544 */ VXI_MOVL,VXT_REG,0x6C,VXT_ADDR,0,VXT_END,
+/* 550 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_currtn,
+/* 558 */ VXT_END,
+/* 559 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 567 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_cvtparm,VXT_END,
+/* 574 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 582 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_div,VXT_END,
+/* 589 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
+/* 597 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equ,VXT_END,
+/* 603 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equnul,
+/* 611 */ VXT_END,
+/* 612 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 620 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_LIT,0,VXI_JSB,
+/* 628 */ VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
+/* 631 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 639 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_JSB,
+/* 647 */ VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
+/* 650 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunret,
+/* 658 */ VXT_END,
+/* 659 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunretals,
+/* 667 */ VXT_END,
+/* 668 */ VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,VXT_GREF,1,VXI_JSB,VXT_XFER,
+/* 676 */ SIZEOF(char *) * (short int)xf_extcall,VXT_END,
+/* 678 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 686 */ 3,VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,
+/* 694 */ VXT_GREF,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
+/* 700 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 708 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,
+/* 716 */ VXT_GREF,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
+/* 722 */ VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,VXT_GREF,1,VXI_JSB,VXT_XFER,
+/* 730 */ SIZEOF(char *) * (short int)xf_extjmp,VXT_END,
+/* 732 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 740 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_exp,VXT_END,
+/* 747 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fetch,
+/* 755 */ VXT_END,
+/* 756 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 764 */ 3,VXI_PUSHAB,VXT_GREF,2,VXI_PUSHL,VXT_LIT,0,VXI_CALLS,
+/* 772 */ VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
+/* 777 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 785 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fgnlookup,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 793 */ VXT_END,
+/* 794 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 802 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnascii,VXT_END,
+/* 809 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 817 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnchar,VXT_END,
+/* 821 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 829 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fndata,VXT_END,
+/* 833 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 841 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 849 */ SIZEOF(char *) * (short int)xf_fnextract,VXT_END,
+/* 851 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 859 */ 3,VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,
+/* 867 */ VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
+/* 872 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 880 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 888 */ SIZEOF(char *) * (short int)xf_fnfind,VXT_END,
+/* 890 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 898 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 906 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfnumber,VXT_END,
+/* 911 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
+/* 919 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget,VXT_END,
+/* 925 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 933 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget2,VXT_END,
+/* 940 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget,
+/* 948 */ VXT_END,
+/* 949 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget1,
+/* 957 */ VXT_END,
+/* 958 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 966 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget1,VXT_END,
+/* 970 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 978 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnincr,VXT_END,
+/* 985 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 993 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnj2,VXT_END,
+/* 1000 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1008 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1016 */ SIZEOF(char *) * (short int)xf_fnj3,VXT_END,
+/* 1018 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1026 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlength,VXT_END,
+/* 1030 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1038 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvname,VXT_END,
+/* 1045 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
+/* 1053 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvnameo2,VXT_END,
+/* 1060 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1068 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvprvname,VXT_END,
+/* 1072 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 1080 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,2,VXT_XFER,
+/* 1088 */ SIZEOF(char *) * (short int)xf_fnname,VXT_END,
+/* 1090 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1098 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnnext,VXT_END,
+/* 1105 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
+/* 1113 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1121 */ SIZEOF(char *) * (short int)xf_fno2,VXT_END,
+/* 1123 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1131 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnorder,VXT_END,
+/* 1138 */ VXI_PUSHL,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,
+/* 1146 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1154 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnp1,VXT_END,
+/* 1159 */ VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,
+/* 1167 */ 4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 1175 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpiece,VXT_END,
+/* 1183 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1191 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqlength,VXT_END,
+/* 1195 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1203 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqsubscript,VXT_END,
+/* 1210 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1218 */ 0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnquery,VXT_END,
+/* 1225 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1233 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnrandom,VXT_END,
+/* 1237 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1245 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnreverse,VXT_END,
+/* 1249 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1257 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack1,VXT_END,
+/* 1261 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1269 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack2,VXT_END,
+/* 1276 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1284 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1292 */ SIZEOF(char *) * (short int)xf_fntext,VXT_END,
+/* 1294 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1302 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1310 */ SIZEOF(char *) * (short int)xf_fntranslate,VXT_END,
+/* 1312 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1320 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnview,VXT_END,
+/* 1324 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 1332 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzascii,VXT_END,
+/* 1339 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1347 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzahandle,VXT_END,
+/* 1351 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1359 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitand,VXT_END,
+/* 1366 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1374 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitcoun,VXT_END,
+/* 1378 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1386 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1394 */ SIZEOF(char *) * (short int)xf_fnzbitfind,VXT_END,
+/* 1396 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1404 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitget,VXT_END,
+/* 1411 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1419 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitlen,VXT_END,
+/* 1423 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1431 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitnot,VXT_END,
+/* 1435 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1443 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitor,VXT_END,
+/* 1450 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1458 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1466 */ SIZEOF(char *) * (short int)xf_fnzbitset,VXT_END,
+/* 1468 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1476 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitstr,VXT_END,
+/* 1483 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1491 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitxor,VXT_END,
+/* 1498 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1506 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzcall,VXT_END,
+/* 1510 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1518 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzchar,VXT_END,
+/* 1522 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1530 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdata,VXT_END,
+/* 1534 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
+/* 1542 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1550 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdate,VXT_END,
+/* 1555 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 1563 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1571 */ SIZEOF(char *) * (short int)xf_fnzextract,VXT_END,
+/* 1573 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1581 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzfile,VXT_END,
+/* 1588 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1596 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1604 */ SIZEOF(char *) * (short int)xf_fnzfind,VXT_END,
+/* 1606 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1614 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetdvi,VXT_END,
+/* 1621 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1629 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetjpi,VXT_END,
+/* 1636 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1644 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetlki,VXT_END,
+/* 1651 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1659 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetsyi,VXT_END,
+/* 1666 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1674 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzj2,VXT_END,
+/* 1681 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1689 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzjobexam,VXT_END,
+/* 1693 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1701 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlength,VXT_END,
+/* 1705 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1713 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlkid,VXT_END,
+/* 1717 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1725 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzm,VXT_END,
+/* 1729 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1737 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1745 */ SIZEOF(char *) * (short int)xf_fnzp1,VXT_END,
+/* 1747 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
+/* 1755 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 1763 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzparse,VXT_END,
+/* 1771 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1779 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpid,VXT_END,
+/* 1783 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 1791 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1799 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpiece,VXT_END,
+/* 1804 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1812 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpopulation,VXT_END,
+/* 1819 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1827 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzprevious,VXT_END,
+/* 1834 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1842 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpriv,VXT_END,
+/* 1846 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzqgblmod,
+/* 1854 */ VXT_END,
+/* 1855 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1863 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1871 */ SIZEOF(char *) * (short int)xf_fnzsearch,VXT_END,
+/* 1873 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1881 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsetprv,VXT_END,
+/* 1885 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1893 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsocket,VXT_END,
+/* 1897 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1905 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1913 */ SIZEOF(char *) * (short int)xf_fnzsubstr,VXT_END,
+/* 1915 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1923 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1931 */ SIZEOF(char *) * (short int)xf_fnztranslate,VXT_END,
+/* 1933 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1941 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsigproc,VXT_END,
+/* 1948 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,6,VXI_PUSHAB,VXT_VAL,
+/* 1956 */ 5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,
+/* 1964 */ VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,7,
+/* 1972 */ VXT_XFER,SIZEOF(char *) * (short int)xf_fnztrnlnm,VXT_END,
+/* 1975 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1983 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwidth,VXT_END,
+/* 1987 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 1995 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_follow,VXT_END,
+/* 2001 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
+/* 2009 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forcenum,VXT_END,
+/* 2015 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forchk1,VXT_END,
+/* 2022 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2030 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forinit,VXT_END,
+/* 2035 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldob,VXI_BRB,VXT_JMP,
/* 2043 */ 1,VXT_END,
-/* 2045 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 2053 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 2061 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 2064 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 2072 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 2080 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 2083 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 2091 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 2099 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 2102 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_getindx,
-/* 2110 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 2116 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_gettruth,
-/* 2124 */ VXT_END,
-/* 2125 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvdata,
-/* 2133 */ VXT_END,
-/* 2134 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2142 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvextnam,VXT_END,
-/* 2146 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvget,
-/* 2154 */ VXT_END,
-/* 2155 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 2163 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvincr,VXT_END,
-/* 2167 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvkill,VXT_END,
-/* 2173 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2181 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnaked,VXT_END,
-/* 2185 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2193 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvname,VXT_END,
-/* 2197 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnext,
-/* 2205 */ VXT_END,
-/* 2206 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 2214 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvo2,VXT_END,
-/* 2218 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvorder,
-/* 2226 */ VXT_END,
-/* 2227 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvput,
-/* 2235 */ VXT_END,
-/* 2236 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvquery,
-/* 2244 */ VXT_END,
-/* 2245 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvrectarg,
-/* 2253 */ VXT_END,
-/* 2254 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvsavtarg,
-/* 2262 */ VXT_END,
-/* 2263 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvzwithdraw,VXT_END,
-/* 2269 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 2277 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,
-/* 2285 */ SIZEOF(char *) * (short int)xf_gvzwrite,VXT_END,
-/* 2287 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_halt,VXT_END,
-/* 2293 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 2301 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_hang,VXT_END,
-/* 2305 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_hardret,VXT_END,
-/* 2309 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2317 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_idiv,VXT_END,
-/* 2324 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_igetsrc,
-/* 2332 */ VXT_END,
-/* 2333 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2341 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_inddevparms,VXT_END,
-/* 2346 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2354 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname,VXT_END,
-/* 2359 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2367 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfun,VXT_END,
-/* 2372 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2380 */ SIZEOF(char *) * (short int)xf_indglvn,VXT_END,
-/* 2382 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2390 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indincr,VXT_END,
-/* 2395 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvadr,VXI_MOVL,VXT_REG,
-/* 2403 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2407 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2415 */ SIZEOF(char *) * (short int)xf_indlvarg,VXT_END,
-/* 2417 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2425 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indname,VXT_END,
-/* 2432 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvnamadr,VXI_MOVL,VXT_REG,
-/* 2440 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2444 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2452 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indo2,VXT_END,
-/* 2459 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2467 */ SIZEOF(char *) * (short int)xf_indpat,VXT_END,
-/* 2469 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2477 */ SIZEOF(char *) * (short int)xf_indrzshow,VXT_END,
-/* 2479 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2487 */ SIZEOF(char *) * (short int)xf_indset,VXT_END,
-/* 2489 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2497 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indtext,VXT_END,
-/* 2505 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2513 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_iocontrol,VXT_END,
-/* 2517 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_iretmvad,
-/* 2525 */ VXT_END,
-/* 2526 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2534 */ SIZEOF(char *) * (short int)xf_iretmval,VXT_END,
-/* 2536 */ VXI_BRB,VXT_JMP,1,VXT_END,
-/* 2540 */ VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2544 */ VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2548 */ VXI_JMP,VXT_VAL,1,VXT_END,
-/* 2552 */ VXI_BEQL,VXT_JMP,1,VXT_END,
-/* 2556 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2563 */ VXI_BNEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2570 */ VXI_BGEQ,VXT_JMP,1,VXT_END,
-/* 2574 */ VXI_BLSS,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2581 */ VXI_BLSS,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2588 */ VXI_BGTR,VXT_JMP,1,VXT_END,
-/* 2592 */ VXI_BLEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2599 */ VXI_BLEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2606 */ VXI_BLEQ,VXT_JMP,1,VXT_END,
-/* 2610 */ VXI_BGTR,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2617 */ VXI_BGTR,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2624 */ VXI_BLSS,VXT_JMP,1,VXT_END,
-/* 2628 */ VXI_BGEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2635 */ VXI_BGEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2642 */ VXI_BNEQ,VXT_JMP,1,VXT_END,
-/* 2646 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2653 */ VXI_BEQL,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2660 */ VXI_BLBC,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
-/* 2666 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
-/* 2674 */ VXT_END,
-/* 2675 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
-/* 2683 */ VXT_END,
-/* 2684 */ VXI_BLBS,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
-/* 2690 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
-/* 2698 */ VXT_END,
-/* 2699 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
-/* 2707 */ VXT_END,
-/* 2708 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,7,VXI_PUSHL,VXT_VAL,
-/* 2716 */ 6,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,
-/* 2724 */ VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,
-/* 2732 */ VXT_XFER,SIZEOF(char *) * (short int)xf_job,VXT_END,
-/* 2735 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_kill,
-/* 2743 */ VXT_END,
-/* 2744 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_killalias,
-/* 2752 */ VXT_END,
-/* 2753 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killall,VXT_END,
-/* 2759 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killaliasall,VXT_END,
-/* 2765 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2773 */ 3,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_labaddr,VXI_MOVL,VXT_REG,
-/* 2781 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2785 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckdecr,
-/* 2793 */ VXT_END,
-/* 2794 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckincr,
-/* 2802 */ VXT_END,
-/* 2803 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2809 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2815 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2821 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2829 */ SIZEOF(char *) * (short int)xf_linefetch,VXT_END,
-/* 2831 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_linestart,VXT_END,
-/* 2835 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 2843 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
-/* 2850 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_lkinit,VXT_END,
-/* 2856 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2864 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
-/* 2871 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lock,
-/* 2879 */ VXT_END,
-/* 2880 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2888 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvpatwrite,VXT_END,
-/* 2895 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwithdraw,
-/* 2903 */ VXT_END,
-/* 2904 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2912 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwrite,VXT_END,
-/* 2916 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2924 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_flt_mod,VXT_END,
-/* 2931 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2939 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_mul,VXT_END,
-/* 2946 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
-/* 2954 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_neg,VXT_END,
-/* 2960 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newintrinsic,VXT_END,
-/* 2967 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newvar,VXT_END,
-/* 2974 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_nullexp,VXI_MOVL,VXT_REG,0x50,
-/* 2982 */ VXT_ADDR,0,VXT_END,
-/* 2985 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 2993 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_numcmp,VXT_END,
-/* 2999 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3007 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3015 */ VXT_LIT,4,VXT_XFER,SIZEOF(char *) * (short int)xf_open,VXT_END,
-/* 3020 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 3028 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_pattern,VXT_END,
-/* 3034 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3042 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpopulation,VXT_END,
-/* 3049 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_putindx,
-/* 3057 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 3063 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 3071 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_rdone,VXT_END,
-/* 3078 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 3086 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_read,VXT_END,
-/* 3093 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 3101 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,3,VXT_XFER,
-/* 3109 */ SIZEOF(char *) * (short int)xf_readfl,VXT_END,
-/* 3111 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_END,
-/* 3115 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_ret,VXT_END,
-/* 3119 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVL,VXT_VAL,2,
-/* 3127 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_retarg,VXT_END,
-/* 3133 */ VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3141 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 3149 */ VXT_END,
-/* 3150 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3158 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 3166 */ VXT_END,
-/* 3167 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3175 */ SIZEOF(char *) * (short int)xf_rterror,VXT_END,
-/* 3177 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3185 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setals2als,VXT_END,
-/* 3189 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3197 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsin2alsct,VXT_END,
-/* 3201 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3209 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsctin2als,VXT_END,
-/* 3213 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3221 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsct2alsct,VXT_END,
-/* 3225 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3233 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2als,VXT_END,
-/* 3237 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3245 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2alsct,VXT_END,
-/* 3249 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3257 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3265 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setextract,VXT_END,
-/* 3270 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3278 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3286 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setp1,VXT_END,
-/* 3291 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3299 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3307 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setpiece,VXT_END,
-/* 3315 */ VXI_BISB2,VXT_LIT,1,VXT_REG,0x5A,VXI_CALLS,VXT_LIT,0,
-/* 3323 */ VXT_XFER,SIZEOF(char *) * (short int)xf_dt_true,VXT_END,
-/* 3326 */ VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3334 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,3,VXI_CALLS,
-/* 3342 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzbrk,VXT_END,
-/* 3347 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3355 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3363 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzextract,VXT_END,
-/* 3368 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3376 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3384 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzp1,VXT_END,
-/* 3389 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3397 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3405 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setzpiece,VXT_END,
-/* 3413 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 3421 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sorts_after,VXT_END,
-/* 3427 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_srchindx,
-/* 3435 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 3441 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
-/* 3449 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
-/* 3455 */ VXI_MOVC3,VXT_LIT,16,VXT_VAL,2,VXT_VAL,1,VXT_END,
-/* 3463 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
-/* 3471 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
-/* 3477 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3485 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_sub,VXT_END,
-/* 3492 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3500 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svget,VXT_END,
-/* 3504 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3512 */ SIZEOF(char *) * (short int)xf_psvput,VXT_END,
-/* 3514 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3522 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svput,VXT_END,
-/* 3526 */ VXI_MOVL,VXT_REG,0x50,VXT_REG,0x5A,VXT_END,
-/* 3532 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tcommit,VXT_END,
-/* 3536 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trollback,VXT_END,
-/* 3543 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trestart,VXT_END,
-/* 3550 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3558 */ 2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tstart,VXT_END,
-/* 3566 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_unlock,VXT_END,
-/* 3572 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3580 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_use,VXT_END,
-/* 3584 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_view,
-/* 3592 */ VXT_END,
-/* 3593 */ VXI_CMPL,VXT_VAL,1,VXT_VAL,2,VXT_END,
-/* 3599 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_write,
-/* 3607 */ VXT_END,
-/* 3608 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wteol,
-/* 3616 */ VXT_END,
-/* 3617 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_wtff,VXT_END,
-/* 3623 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wtone,
-/* 3631 */ VXT_END,
-/* 3632 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wttab,
-/* 3640 */ VXT_END,
-/* 3641 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_xkill,
-/* 3649 */ VXT_END,
-/* 3650 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3658 */ SIZEOF(char *) * (short int)xf_xnew,VXT_END,
-/* 3660 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zallocate,
-/* 3668 */ VXT_END,
-/* 3669 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3677 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zattach,VXT_END,
-/* 3681 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3689 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zcompile,VXT_END,
-/* 3693 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3697 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zdeallocate,
-/* 3705 */ VXT_END,
-/* 3706 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3714 */ 1,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_zedit,VXT_END,
-/* 3721 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zg1,VXT_END,
-/* 3728 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHL,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
-/* 3736 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zgoto,VXT_END,
-/* 3744 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zhalt,
-/* 3752 */ VXT_END,
-/* 3753 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3761 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zhelp,VXT_END,
-/* 3765 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3773 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zlink,VXT_END,
-/* 3777 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 3785 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zmess,VXT_END,
-/* 3789 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zprevious,
-/* 3797 */ VXT_END,
-/* 3798 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
-/* 3806 */ 4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3814 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_zprint,VXT_END,
-/* 3822 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,
-/* 3830 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
-/* 3838 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
-/* 3840 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3848 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
-/* 3856 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
-/* 3858 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3866 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3873 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3881 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3888 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3896 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zsystem,VXT_END,
-/* 3900 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_ztcommit,
-/* 3908 */ VXT_END,
-/* 3909 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztstart,VXT_END,
-/* 3915 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_merge,VXT_END,
-/* 3921 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3929 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
-/* 3933 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3941 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
-/* 3945 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,
-/* 3953 */ SIZEOF(char *) * (short int)xf_indmerge,VXT_END,
-/* 3955 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_m_srchindx,
-/* 3963 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 3969 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zwritesvn,
-/* 3977 */ VXT_END,
-/* 3978 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3986 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwrite,VXT_END,
-/* 3990 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_igetdst,VXI_MOVL,VXT_REG,0x50,
-/* 3998 */ VXT_ADDR,0,VXT_END,
-/* 4001 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4009 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget1,VXT_END,
-/* 4013 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnpop,
-/* 4021 */ VXT_END,
-/* 4022 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnslot,
-/* 4030 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 4036 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 4044 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indsavglvn,VXT_END,
-/* 4049 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 4057 */ SIZEOF(char *) * (short int)xf_indsavlvn,VXT_END,
-/* 4059 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4067 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshlvn,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 4075 */ VXT_END,
-/* 4076 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 4084 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_savgvn,VXT_END,
-/* 4088 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_savlvn,
-/* 4096 */ VXT_END,
-/* 4097 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4105 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_shareslot,VXT_END,
-/* 4109 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4117 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_stoglvn,VXT_END,
-/* 4121 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4129 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshgvn,VXT_END,
-/* 4133 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 4141 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname2,VXT_END,
-/* 4148 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 4156 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget2,VXT_END,
-/* 4160 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_indmerge2,
-/* 4168 */ VXT_END,
-/* 4169 */ 361,381,371,2536,2544,2540,2803,2815,
-/* 4177 */ 2809,0,0,0,502,478,469,0,
-/* 4185 */ 0,465,2045,2083,2064,2684,2699,2690,
-/* 4193 */ 2660,2675,2666,2552,2563,2556,2642,2653,
-/* 4201 */ 2646,2588,2599,2592,2606,2617,2610,2624,
-/* 4209 */ 2635,2628,2570,2581,2574,2015,2035,2025,
-/* 4217 */ 391,411,401};
+/* 2045 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldol,VXI_JMP,VXT_JMP,
+/* 2053 */ 1,VXT_END,
+/* 2055 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldow,VXI_BRW,VXT_JMP,
+/* 2063 */ 1,VXT_END,
+/* 2065 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 2073 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 2081 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2084 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 2092 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 2100 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2103 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 2111 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 2119 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2122 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_getindx,
+/* 2130 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 2136 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_gettruth,
+/* 2144 */ VXT_END,
+/* 2145 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvdata,
+/* 2153 */ VXT_END,
+/* 2154 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2162 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvextnam,VXT_END,
+/* 2166 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvget,
+/* 2174 */ VXT_END,
+/* 2175 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 2183 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvincr,VXT_END,
+/* 2187 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvkill,VXT_END,
+/* 2193 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2201 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnaked,VXT_END,
+/* 2205 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2213 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvname,VXT_END,
+/* 2217 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnext,
+/* 2225 */ VXT_END,
+/* 2226 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 2234 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvo2,VXT_END,
+/* 2238 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvorder,
+/* 2246 */ VXT_END,
+/* 2247 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvput,
+/* 2255 */ VXT_END,
+/* 2256 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvquery,
+/* 2264 */ VXT_END,
+/* 2265 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvrectarg,
+/* 2273 */ VXT_END,
+/* 2274 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvsavtarg,
+/* 2282 */ VXT_END,
+/* 2283 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvzwithdraw,VXT_END,
+/* 2289 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 2297 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,
+/* 2305 */ SIZEOF(char *) * (short int)xf_gvzwrite,VXT_END,
+/* 2307 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_halt,VXT_END,
+/* 2313 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 2321 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_hang,VXT_END,
+/* 2325 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_hardret,VXT_END,
+/* 2329 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2337 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_idiv,VXT_END,
+/* 2344 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_igetsrc,
+/* 2352 */ VXT_END,
+/* 2353 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2361 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_inddevparms,VXT_END,
+/* 2366 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2374 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname,VXT_END,
+/* 2379 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2387 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfun,VXT_END,
+/* 2392 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2400 */ SIZEOF(char *) * (short int)xf_indglvn,VXT_END,
+/* 2402 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2410 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indincr,VXT_END,
+/* 2415 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvadr,VXI_MOVL,VXT_REG,
+/* 2423 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2427 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2435 */ SIZEOF(char *) * (short int)xf_indlvarg,VXT_END,
+/* 2437 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2445 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indname,VXT_END,
+/* 2452 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvnamadr,VXI_MOVL,VXT_REG,
+/* 2460 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2464 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2472 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indo2,VXT_END,
+/* 2479 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2487 */ SIZEOF(char *) * (short int)xf_indpat,VXT_END,
+/* 2489 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2497 */ SIZEOF(char *) * (short int)xf_indrzshow,VXT_END,
+/* 2499 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2507 */ SIZEOF(char *) * (short int)xf_indset,VXT_END,
+/* 2509 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2517 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indtext,VXT_END,
+/* 2525 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2533 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_iocontrol,VXT_END,
+/* 2537 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_iretmvad,
+/* 2545 */ VXT_END,
+/* 2546 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2554 */ SIZEOF(char *) * (short int)xf_iretmval,VXT_END,
+/* 2556 */ VXI_BRB,VXT_JMP,1,VXT_END,
+/* 2560 */ VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2564 */ VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2568 */ VXI_JMP,VXT_VAL,1,VXT_END,
+/* 2572 */ VXI_BEQL,VXT_JMP,1,VXT_END,
+/* 2576 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2583 */ VXI_BNEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2590 */ VXI_BGEQ,VXT_JMP,1,VXT_END,
+/* 2594 */ VXI_BLSS,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2601 */ VXI_BLSS,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2608 */ VXI_BGTR,VXT_JMP,1,VXT_END,
+/* 2612 */ VXI_BLEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2619 */ VXI_BLEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2626 */ VXI_BLEQ,VXT_JMP,1,VXT_END,
+/* 2630 */ VXI_BGTR,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2637 */ VXI_BGTR,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2644 */ VXI_BLSS,VXT_JMP,1,VXT_END,
+/* 2648 */ VXI_BGEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2655 */ VXI_BGEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2662 */ VXI_BNEQ,VXT_JMP,1,VXT_END,
+/* 2666 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2673 */ VXI_BEQL,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2680 */ VXI_BLBC,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
+/* 2686 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
+/* 2694 */ VXT_END,
+/* 2695 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
+/* 2703 */ VXT_END,
+/* 2704 */ VXI_BLBS,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
+/* 2710 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
+/* 2718 */ VXT_END,
+/* 2719 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
+/* 2727 */ VXT_END,
+/* 2728 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,7,VXI_PUSHL,VXT_VAL,
+/* 2736 */ 6,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,
+/* 2744 */ VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,
+/* 2752 */ VXT_XFER,SIZEOF(char *) * (short int)xf_job,VXT_END,
+/* 2755 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_kill,
+/* 2763 */ VXT_END,
+/* 2764 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_killalias,
+/* 2772 */ VXT_END,
+/* 2773 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killall,VXT_END,
+/* 2779 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killaliasall,VXT_END,
+/* 2785 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2793 */ 3,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_labaddr,VXI_MOVL,VXT_REG,
+/* 2801 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2805 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckdecr,
+/* 2813 */ VXT_END,
+/* 2814 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckincr,
+/* 2822 */ VXT_END,
+/* 2823 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2829 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2835 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2841 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2849 */ SIZEOF(char *) * (short int)xf_linefetch,VXT_END,
+/* 2851 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_linestart,VXT_END,
+/* 2855 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 2863 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
+/* 2870 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_lkinit,VXT_END,
+/* 2876 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2884 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
+/* 2891 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lock,
+/* 2899 */ VXT_END,
+/* 2900 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2908 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvpatwrite,VXT_END,
+/* 2915 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwithdraw,
+/* 2923 */ VXT_END,
+/* 2924 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2932 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwrite,VXT_END,
+/* 2936 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2944 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_flt_mod,VXT_END,
+/* 2951 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2959 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_mul,VXT_END,
+/* 2966 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
+/* 2974 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_neg,VXT_END,
+/* 2980 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newintrinsic,VXT_END,
+/* 2987 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newvar,VXT_END,
+/* 2994 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_nullexp,VXI_MOVL,VXT_REG,0x50,
+/* 3002 */ VXT_ADDR,0,VXT_END,
+/* 3005 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 3013 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_numcmp,VXT_END,
+/* 3019 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3027 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3035 */ VXT_LIT,4,VXT_XFER,SIZEOF(char *) * (short int)xf_open,VXT_END,
+/* 3040 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 3048 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_pattern,VXT_END,
+/* 3054 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3062 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpopulation,VXT_END,
+/* 3069 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_putindx,
+/* 3077 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3083 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 3091 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_rdone,VXT_END,
+/* 3098 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 3106 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_read,VXT_END,
+/* 3113 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 3121 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,3,VXT_XFER,
+/* 3129 */ SIZEOF(char *) * (short int)xf_readfl,VXT_END,
+/* 3131 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_END,
+/* 3135 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_ret,VXT_END,
+/* 3139 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVL,VXT_VAL,2,
+/* 3147 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_retarg,VXT_END,
+/* 3153 */ VXI_PUSHAB,VXT_GREF,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3161 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 3169 */ VXT_END,
+/* 3170 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3178 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 3186 */ VXT_END,
+/* 3187 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3195 */ SIZEOF(char *) * (short int)xf_rterror,VXT_END,
+/* 3197 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3205 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setals2als,VXT_END,
+/* 3209 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3217 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsin2alsct,VXT_END,
+/* 3221 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3229 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsctin2als,VXT_END,
+/* 3233 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3241 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsct2alsct,VXT_END,
+/* 3245 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3253 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2als,VXT_END,
+/* 3257 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3265 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2alsct,VXT_END,
+/* 3269 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3277 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3285 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setextract,VXT_END,
+/* 3290 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3298 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3306 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setp1,VXT_END,
+/* 3311 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3319 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3327 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setpiece,VXT_END,
+/* 3335 */ VXI_BISB2,VXT_LIT,1,VXT_REG,0x5A,VXI_CALLS,VXT_LIT,0,
+/* 3343 */ VXT_XFER,SIZEOF(char *) * (short int)xf_dt_true,VXT_END,
+/* 3346 */ VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3354 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,3,VXI_CALLS,
+/* 3362 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzbrk,VXT_END,
+/* 3367 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3375 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3383 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzextract,VXT_END,
+/* 3388 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3396 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3404 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzp1,VXT_END,
+/* 3409 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3417 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3425 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setzpiece,VXT_END,
+/* 3433 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 3441 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sorts_after,VXT_END,
+/* 3447 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_srchindx,
+/* 3455 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3461 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
+/* 3469 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
+/* 3475 */ VXI_MOVC3,VXT_LIT,16,VXT_VAL,2,VXT_VAL,1,VXT_END,
+/* 3483 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
+/* 3491 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
+/* 3497 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3505 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_sub,VXT_END,
+/* 3512 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3520 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svget,VXT_END,
+/* 3524 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3532 */ SIZEOF(char *) * (short int)xf_psvput,VXT_END,
+/* 3534 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3542 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svput,VXT_END,
+/* 3546 */ VXI_MOVL,VXT_REG,0x50,VXT_REG,0x5A,VXT_END,
+/* 3552 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tcommit,VXT_END,
+/* 3556 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trollback,VXT_END,
+/* 3563 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trestart,VXT_END,
+/* 3570 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3578 */ 2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tstart,VXT_END,
+/* 3586 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_unlock,VXT_END,
+/* 3592 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3600 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_use,VXT_END,
+/* 3604 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_view,
+/* 3612 */ VXT_END,
+/* 3613 */ VXI_CMPL,VXT_VAL,1,VXT_VAL,2,VXT_END,
+/* 3619 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_write,
+/* 3627 */ VXT_END,
+/* 3628 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wteol,
+/* 3636 */ VXT_END,
+/* 3637 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_wtff,VXT_END,
+/* 3643 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wtone,
+/* 3651 */ VXT_END,
+/* 3652 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wttab,
+/* 3660 */ VXT_END,
+/* 3661 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_xkill,
+/* 3669 */ VXT_END,
+/* 3670 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3678 */ SIZEOF(char *) * (short int)xf_xnew,VXT_END,
+/* 3680 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zallocate,
+/* 3688 */ VXT_END,
+/* 3689 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3697 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zattach,VXT_END,
+/* 3701 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3709 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zcompile,VXT_END,
+/* 3713 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3717 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zdeallocate,
+/* 3725 */ VXT_END,
+/* 3726 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3734 */ 1,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_zedit,VXT_END,
+/* 3741 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zg1,VXT_END,
+/* 3748 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHL,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
+/* 3756 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zgoto,VXT_END,
+/* 3764 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zhalt,
+/* 3772 */ VXT_END,
+/* 3773 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3781 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zhelp,VXT_END,
+/* 3785 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3793 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zlink,VXT_END,
+/* 3797 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 3805 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zmess,VXT_END,
+/* 3809 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zprevious,
+/* 3817 */ VXT_END,
+/* 3818 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
+/* 3826 */ 4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3834 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_zprint,VXT_END,
+/* 3842 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,
+/* 3850 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
+/* 3858 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
+/* 3860 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3868 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
+/* 3876 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
+/* 3878 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3886 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3893 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3901 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3908 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3916 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zsystem,VXT_END,
+/* 3920 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_ztcommit,
+/* 3928 */ VXT_END,
+/* 3929 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztstart,VXT_END,
+/* 3935 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_merge,VXT_END,
+/* 3941 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3949 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
+/* 3953 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3961 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
+/* 3965 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,
+/* 3973 */ SIZEOF(char *) * (short int)xf_indmerge,VXT_END,
+/* 3975 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_m_srchindx,
+/* 3983 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3989 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zwritesvn,
+/* 3997 */ VXT_END,
+/* 3998 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4006 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwrite,VXT_END,
+/* 4010 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_igetdst,VXI_MOVL,VXT_REG,0x50,
+/* 4018 */ VXT_ADDR,0,VXT_END,
+/* 4021 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4029 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget1,VXT_END,
+/* 4033 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnpop,
+/* 4041 */ VXT_END,
+/* 4042 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnslot,
+/* 4050 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 4056 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 4064 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indsavglvn,VXT_END,
+/* 4069 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 4077 */ SIZEOF(char *) * (short int)xf_indsavlvn,VXT_END,
+/* 4079 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4087 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshlvn,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 4095 */ VXT_END,
+/* 4096 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 4104 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_savgvn,VXT_END,
+/* 4108 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_savlvn,
+/* 4116 */ VXT_END,
+/* 4117 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4125 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_shareslot,VXT_END,
+/* 4129 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4137 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_stoglvn,VXT_END,
+/* 4141 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4149 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshgvn,VXT_END,
+/* 4153 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 4161 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname2,VXT_END,
+/* 4168 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 4176 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget2,VXT_END,
+/* 4180 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_indmerge2,
+/* 4188 */ VXT_END,
+/* 4189 */ 366,386,376,2556,2564,2560,2823,2835,
+/* 4197 */ 2829,0,0,0,507,483,474,0,
+/* 4205 */ 0,470,2065,2103,2084,2704,2719,2710,
+/* 4213 */ 2680,2695,2686,2572,2583,2576,2662,2673,
+/* 4221 */ 2666,2608,2619,2612,2626,2637,2630,2644,
+/* 4229 */ 2655,2648,2590,2601,2594,2035,2055,2045,
+/* 4237 */ 396,416,406};
diff --git a/sr_vvms/ttt.txt b/sr_vvms/ttt.txt
index c678a2f..15740cc 100644
--- a/sr_vvms/ttt.txt
+++ b/sr_vvms/ttt.txt
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
-; Copyright 2001, 2013 Fidelity Information Services, Inc ;
+; Copyright 2001, 2014 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
@@ -419,12 +419,16 @@ OC_FNZPRIV: pushab val.0
OC_FNZQGBLMOD: pushab val.0
calls #1,xfer.xf_fnzqgblmod
OC_FNZSEA: pushab val.0
+ pushl val.3
pushl val.2
pushab val.1
- calls #3,xfer.xf_fnzsearch
+ calls #4,xfer.xf_fnzsearch
OC_FNZSETPRV: pushab val.0
pushab val.1
calls #2,xfer.xf_fnzsetprv
+OC_FNZSOCKET: irepab val.2
+ pushab val.0
+ calls val.1,xfer.xf_fnzsocket
OC_FNZSUBSTR: pushab val.0 ; Destination mval
pushl val.3 ; max byte length
pushl val.2 ; starting character position
diff --git a/sr_vvms/zshow_devices.c b/sr_vvms/zshow_devices.c
index f4bc387..0a7ee2d 100644
--- a/sr_vvms/zshow_devices.c
+++ b/sr_vvms/zshow_devices.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -34,11 +34,9 @@
#include "zshow_params.h"
#include "mvalconv.h"
-typedef struct
-{
- unsigned short mem;
- unsigned short grp;
-} uic_struct;
+GBLREF boolean_t ctrlc_on;
+GBLREF io_log_name *io_root_log_name;
+GBLREF io_pair *io_std_device;
LITREF nametabent dev_param_names[];
LITREF uint4 dev_param_index[];
@@ -46,6 +44,12 @@ LITREF zshow_index zshow_param_index[];
static readonly char space_text[] = {' '};
+typedef struct
+{
+ unsigned short mem;
+ unsigned short grp;
+} uic_struct;
+
#define ZS_ONE_OUT(V, TEXT) ((V)->str.len = 1, (V)->str.addr = (TEXT), zshow_output(output, &(V)->str))
#define ZS_STR_OUT(V, TEXT) ((V)->str.len = SIZEOF((TEXT)) - 1, (V)->str.addr = (TEXT), zshow_output(output, &(V)->str))
#define ZS_PARM_SP(V, TEXT) ((V)->str.len = dev_param_names[dev_param_index[zshow_param_index[(TEXT)].letter] + \
@@ -57,10 +61,6 @@ static readonly char space_text[] = {' '};
(V)->str.addr = dev_param_names[dev_param_index[zshow_param_index[(TEXT)].letter] + \
zshow_param_index[(TEXT)].offset ].name, zshow_output(output, &(V)->str), ZS_ONE_OUT((V), equal_text))
-GBLREF bool ctrlc_on;
-GBLREF io_log_name *io_root_log_name;
-GBLREF io_pair *io_std_device;
-
void zshow_devices(zshow_out *output)
{
static readonly char filchar_text[] = "CHARACTERS";
@@ -125,7 +125,9 @@ void zshow_devices(zshow_out *output)
,"BOUND"
,"CREATED"
};
- static readonly char morereadtime_text[] = "MOREREADTIME=";
+ static readonly char morereadtime_text[] = "MOREREADTIME=";
+ struct XABPRO *xabpro;
+ uic_struct uic;
v.mvtype = MV_STR;
for (l = io_root_log_name; l != 0; l = l->next)
@@ -346,9 +348,6 @@ void zshow_devices(zshow_out *output)
if (f->fab$l_xab)
{
/* smw need to handle other XABs and uic as octal */
- struct XABPRO *xabpro;
- uic_struct uic;
-
ZS_PARM_EQU(&v, zshow_uic);
ZS_ONE_OUT(&v, quote_text);
xabpro = f->fab$l_xab;
diff --git a/sr_x86_64/auto_zlink_sp.c b/sr_x86_64/auto_zlink_sp.c
index 2dccb7f..b622278 100644
--- a/sr_x86_64/auto_zlink_sp.c
+++ b/sr_x86_64/auto_zlink_sp.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2008, 2010 Fidelity Information Services, Inc *
+ * Copyright 2008, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -69,7 +69,7 @@ short opcode_correct(unsigned char *curr_pc, short opcode, short reg_opcode, sho
}
-short valid_calling_sequence(unsigned char *pc)
+short valid_calling_sequence(mach_inst *pc)
{
short curr_offset = 0, inst_sz;
@@ -82,10 +82,11 @@ short valid_calling_sequence(unsigned char *pc)
modrm_byte_long.modrm.r_m = GTM_REG_XFER_TABLE;
/* inst = call off(%reg_xfer) */
- if (curr_offset += opcode_correct(pc, I386_INS_Grp5_Prefix, I386_INS_CALL_Ev, TRUE, GTM_REG_XFER_TABLE))
+ if (curr_offset += opcode_correct((unsigned char*)pc, I386_INS_Grp5_Prefix, I386_INS_CALL_Ev, TRUE, GTM_REG_XFER_TABLE))
{
/* inst is :: mov R0 = MEM */
- inst_sz = 1 + opcode_correct((pc - curr_offset),I386_INS_MOV_Gv_Ev,I386_REG_RDI,TRUE,GTM_REG_PV & 0x7);
+ inst_sz = 1 + opcode_correct(((unsigned char*)pc) - curr_offset, I386_INS_MOV_Gv_Ev, I386_REG_RDI, TRUE,
+ GTM_REG_PV & 0x7);
switch(inst_sz - 1)
{
case FALSE :
@@ -100,12 +101,13 @@ short valid_calling_sequence(unsigned char *pc)
rtnhdr_off = (int4) *((int4 *)(pc - curr_offset - 4));
break;
default :
- GTMASSERT;
+ assertpro(FALSE && (inst_sz - 1));
}
curr_offset += inst_sz;
/* if invalid, would've returned before... */
/* inst is :: mov R1 = MEM */
- inst_sz = 1 + opcode_correct((pc - curr_offset),I386_INS_MOV_Gv_Ev,I386_REG_RSI,TRUE,GTM_REG_PV & 0x7);
+ inst_sz = 1 + opcode_correct(((unsigned char*)pc) - curr_offset, I386_INS_MOV_Gv_Ev, I386_REG_RSI, TRUE,
+ GTM_REG_PV & 0x7);
switch(inst_sz - 1)
{
case FALSE :
@@ -120,7 +122,7 @@ short valid_calling_sequence(unsigned char *pc)
labaddr_off = (int4) *((int4 *)(pc - curr_offset - 4));
break;
default :
- GTMASSERT;
+ assertpro(FALSE && (inst_sz - 1));
}
return TRUE;
}
diff --git a/sr_x86_64/auto_zlink_sp.h b/sr_x86_64/auto_zlink_sp.h
index 415fca4..99da65b 100644
--- a/sr_x86_64/auto_zlink_sp.h
+++ b/sr_x86_64/auto_zlink_sp.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2007, 2010 Fidelity Information Services, Inc *
+ * Copyright 2007, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -20,7 +20,7 @@
#define MOD_LONG_SZ 6
short opcode_correct(unsigned char *curr_pc, short opcode, short reg_opcode, short is_rm, short r_m);
-short valid_calling_sequence(unsigned char *pc);
+short valid_calling_sequence(mach_inst *pc);
#define VALID_CALLING_SEQUENCE(pc) valid_calling_sequence(pc)
#define RTNHDR_PV_OFF(pc) rtnhdr_off
diff --git a/sr_x86_64/cmerrors_ctl.c b/sr_x86_64/cmerrors_ctl.c
index 0d89e8f..02581fe 100644
--- a/sr_x86_64/cmerrors_ctl.c
+++ b/sr_x86_64/cmerrors_ctl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
diff --git a/sr_x86_64/cmierrors_ctl.c b/sr_x86_64/cmierrors_ctl.c
index d8493c8..3656c97 100644
--- a/sr_x86_64/cmierrors_ctl.c
+++ b/sr_x86_64/cmierrors_ctl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
diff --git a/sr_x86_64/gdeerrors_ctl.c b/sr_x86_64/gdeerrors_ctl.c
index 07cc7be..d43120c 100644
--- a/sr_x86_64/gdeerrors_ctl.c
+++ b/sr_x86_64/gdeerrors_ctl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
diff --git a/sr_x86_64/merrors_ansi.h b/sr_x86_64/merrors_ansi.h
index 0df7c77..20e9320 100644
--- a/sr_x86_64/merrors_ansi.h
+++ b/sr_x86_64/merrors_ansi.h
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -93,7 +93,7 @@ const static readonly int error_ansi[] = {
7, /* GVUNDEF */
0, /* TRANSNEST */
0, /* INDEXTRACHARS */
- 0, /* UNUSEDMSG260 */
+ 0, /* CORRUPTNODE */
0, /* INDRMAXLEN */
0, /* INSFFBCNT */
0, /* INTEGERRS */
@@ -642,7 +642,7 @@ const static readonly int error_ansi[] = {
0, /* JNLRDONLY */
0, /* ANCOMPTINC */
0, /* ABNCOMPTINC */
- 0, /* UNUSEDMSG809 */
+ 0, /* RECLOAD */
0, /* SOCKNOTFND */
0, /* CURRSOCKOFR */
79, /* SOCKETEXIST */
@@ -822,16 +822,16 @@ const static readonly int error_ansi[] = {
0, /* RENAMEFAIL */
0, /* FILERENAME */
0, /* JNLBUFINFO */
- 0, /* UNUSEDMSG989 */
- 0, /* UNUSEDMSG990 */
+ 0, /* SDSEEKERR */
+ 0, /* LOCALSOCKREQ */
0, /* TPNOTACID */
0, /* JNLSETDATA2LONG */
0, /* JNLNEWREC */
0, /* REPLFTOKSEM */
- 0, /* UNUSEDMSG995 */
+ 0, /* SOCKNOTPASSED */
0, /* EXTRIOERR */
0, /* EXTRCLOSEERR */
- 0, /* UNUSEDMSG998 */
+ 0, /* CONNSOCKREQ */
0, /* REPLEXITERR */
0, /* MUDESTROYSUC */
0, /* DBRNDWN */
@@ -912,7 +912,7 @@ const static readonly int error_ansi[] = {
0, /* SYSTEMVALUE */
0, /* SIZENOTVALID4 */
0, /* STRNOTVALID */
- 0, /* UNUSEDMSG1079 */
+ 0, /* CREDNOTPASSED */
0, /* ERRWETRAP */
0, /* TRACINGON */
0, /* CITABENV */
@@ -942,7 +942,7 @@ const static readonly int error_ansi[] = {
0, /* MAXBTLEVEL */
35, /* INVMNEMCSPC */
0, /* JNLALIGNSZCHG */
- 0, /* UNUSEDMSG1109 */
+ 0, /* SEFCTNEEDSFULLB */
0, /* GVFAILCORE */
0, /* DBCDBNOCERTIFY */
0, /* DBFRZRESETSUC */
@@ -1089,7 +1089,7 @@ const static readonly int error_ansi[] = {
0, /* REPLINSTSTNDALN */
0, /* REPLREQROLLBACK */
0, /* REQROLLBACK */
- 0, /* UNUSEDMSG1256 */
+ 0, /* INVOBJFILE */
0, /* SRCSRVEXISTS */
0, /* SRCSRVNOTEXIST */
0, /* SRCSRVTOOMANY */
@@ -1250,7 +1250,7 @@ const static readonly int error_ansi[] = {
0, /* MUUSERECOV */
0, /* SECNOTSUPPLEMENTARY */
0, /* SUPRCVRNEEDSSUPSRC */
- 0, /* UNUSEDMSG1417 */
+ 0, /* PEERPIDMISMATCH */
0, /* SETITIMERFAILED */
0, /* UPDSYNC2MTINS */
0, /* UPDSYNCINSTFILE */
@@ -1380,4 +1380,31 @@ const static readonly int error_ansi[] = {
0, /* TLSIOERROR */
0, /* TLSRENEGOTIATE */
0, /* REPLNOTLS */
+ 0, /* COLTRANSSTR2LONG */
+ 0, /* SOCKPASS */
+ 0, /* SOCKACCEPT */
+ 0, /* NOSOCKHANDLE */
+ 0, /* TRIGLOADFAIL */
+ 0, /* SOCKPASSDATAMIX */
+ 0, /* NOGTCMDB */
+ 0, /* NOUSERDB */
+ 0, /* DSENOTOPEN */
+ 0, /* ZSOCKETATTR */
+ 0, /* ZSOCKETNOTSOCK */
+ 0, /* CHSETALREADY */
+ 0, /* DSEMAXBLKSAV */
+ 0, /* BLKINVALID */
+ 0, /* CANTBITMAP */
+ 0, /* AIMGBLKFAIL */
+ 0, /* GTMDISTUNVERIF */
+ 0, /* CRYPTNOAPPEND */
+ 0, /* CRYPTNOSEEK */
+ 0, /* CRYPTNOTRUNC */
+ 0, /* CRYPTNOKEYSPEC */
+ 0, /* CRYPTNOOVERRIDE */
+ 0, /* CRYPTKEYTOOBIG */
+ 0, /* CRYPTBADWRTPOS */
+ 13, /* LABELNOTFND */
+ 0, /* RELINKCTLERR */
+ 0, /* INVLINKTMPDIR */
};
diff --git a/sr_x86_64/merrors_ctl.c b/sr_x86_64/merrors_ctl.c
index c8412e9..4c4ea08 100644
--- a/sr_x86_64/merrors_ctl.c
+++ b/sr_x86_64/merrors_ctl.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001,2013 Fidelity Information Services, Inc *
+ * Copyright 2001,2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -42,8 +42,8 @@ LITDEF err_msg merrors[] = {
"DBRDERR", "Cannot read database file !AD after opening", 2,
"CCEDUMPNOW", "", 0,
"DEVPARINAP", "Device parameter inappropriate to this command", 0,
- "RECORDSTAT", "!AD:!_ Key cnt: !UL max subsc len: !UL max rec len: !UL max node len: !UL", 6,
- "NOTGBL", "!_!AD!/!_!_!_\"^\" Expected", 2,
+ "RECORDSTAT", "!AD:!_ Key cnt: !@ZQ max subsc len: !UL max rec len: !UL max node len: !UL", 6,
+ "NOTGBL", "Expected a global variable name starting with an up-arrow (^): !AD", 2,
"DEVPARPROT", "The protection specification is invalid", 0,
"PREMATEOF", "Premature end of file detected", 0,
"GVINVALID", "!_!AD!/!_!_!_Invalid global name", 2,
@@ -95,7 +95,7 @@ LITDEF err_msg merrors[] = {
"GVUNDEF", "Global variable undefined: !AD", 2,
"TRANSNEST", "Maximum transaction nesting levels exceeded", 0,
"INDEXTRACHARS", "Indirection string contains extra trailing characters", 0,
- "UNUSEDMSG260", "INDMAXNEST Last used in V6.0-000", 0,
+ "CORRUPTNODE", "Corrupt input in Record # !UL, Key #!UL; resuming with next global node", 2,
"INDRMAXLEN", "Maximum length !UL of an indirection argument was exceeded", 1,
"INSFFBCNT", "Insufficient byte count quota left for requested operation", 0,
"INTEGERRS", "Database integrity errors", 0,
@@ -644,7 +644,7 @@ LITDEF err_msg merrors[] = {
"JNLRDONLY", "Journal file !AD read only", 2,
"ANCOMPTINC", "Deviceparameter !AD is not compatible with any other deviceparameters in the !AD command", 4,
"ABNCOMPTINC", "Deviceparameter !AD and deviceparameter !AD are not compatible in the !AD command", 6,
- "UNUSEDMSG809", "GTMSECSHRLOGF last used in V5.5-000", 0,
+ "RECLOAD", "Error loading record number: !UL!/", 1,
"SOCKNOTFND", "Socket !AD not found", 2,
"CURRSOCKOFR", "Current socket of index !UL is out of range. There are only !UL sockets.", 2,
"SOCKETEXIST", "Socket !AD already exists", 2,
@@ -824,16 +824,16 @@ LITDEF err_msg merrors[] = {
"RENAMEFAIL", "Rename of file !AD to !AD failed", 4,
"FILERENAME", "File !AD is renamed to !AD", 4,
"JNLBUFINFO", "Pid 0x!XL!/ dsk 0x!XL free 0x!XL bytcnt 0x!XL io_in_prog 0x!XL fsync_in_prog 0x!XL!/ dskaddr 0x!XL freeaddr 0x!XL qiocnt 0x!XL now_writer 0x!XL fsync_pid 0x!XL!/filesize 0x!XL cycle 0x!XL errcnt 0x!XL wrtsize 0x!XL fsync_dskaddr 0x!XL", 16,
- "UNUSEDMSG989", "JNLQIOLOCKED : Last used in V4.4-000", 0,
- "UNUSEDMSG990", "JNLEOFPREZERO : Last used in V4.4-000", 0,
+ "SDSEEKERR", "Sequential device seek error - !AD", 2,
+ "LOCALSOCKREQ", "LOCAL socket required", 0,
"TPNOTACID", "!AD at !AD in a final TP retry violates ACID properties of a TRANSACTION; indefinite RESTARTs may occur !AD !AD", 8,
"JNLSETDATA2LONG", "SET journal record has data of length !UL. Target system cannot handle data more than !UL bytes.", 2,
"JNLNEWREC", "Target system cannot recognize journal record of type !UL, last recognized type is !UL", 2,
"REPLFTOKSEM", "Error with replication semaphores for instance file !AD", 2,
- "UNUSEDMSG995", "GETCWD : Last used before V4.0-001E", 0,
+ "SOCKNOTPASSED", "Socket message contained no passed socket descriptors", 0,
"EXTRIOERR", "Error writing extract file !AD", 2,
"EXTRCLOSEERR", "Error closing extract file !AD", 2,
- "UNUSEDMSG998", "TRUNCATE : Last used in V4.3-001F", 0,
+ "CONNSOCKREQ", "Socket not connected", 0,
"REPLEXITERR", "Replication process encountered an error while exiting", 0,
"MUDESTROYSUC", "Global section (!AD) corresponding to file !AD successfully destroyed", 4,
"DBRNDWN", "Error during global database rundown for region !AD.!/Notify those responsible for proper database operation.", 2,
@@ -872,7 +872,7 @@ LITDEF err_msg merrors[] = {
"NOCHLEFT", "Unhandled condition exception (all handlers exhausted) - process terminating", 0,
"MULOGNAMEDEF", "Logical name !AD, needed to start replication server is already defined for this job. !/Check for an existing or improperly terminated server.", 2,
"BUFOWNERSTUCK", "Pid !UL waiting for Pid !UL to finish disk-read of block !UL [0x!XL].!/Been waiting for !UL minutes. read_in_progress=!UL : rip_latch = !UL.", 7,
- "ACTIVATEFAIL", "Failed to activate passive source server for secondary instance !AD", 2,
+ "ACTIVATEFAIL", "Cannot activate passive source server on instance !AD while a receiver server and/or update process is running", 2,
"DBRNDWNWRN", "Global section of database file !AD not rundown successfully by pid !UL [0x!XL]. Global section was not removed.", 4,
"DLLNOOPEN", "Failed to load external dynamic library !AD", 2,
"DLLNORTN", "Failed to look up the location of the symbol !AD", 2,
@@ -914,7 +914,7 @@ LITDEF err_msg merrors[] = {
"SYSTEMVALUE", "Invalid value for $SYSTEM (!AD)", 2,
"SIZENOTVALID4", "Size (in bytes) must be either 1, 2, or 4", 0,
"STRNOTVALID", "Error: cannot convert !AD value to valid value", 2,
- "UNUSEDMSG1079", "RECNOCREJNL : Last used in V4.3-001F", 0,
+ "CREDNOTPASSED", "Socket message contained no passed credentials", 0,
"ERRWETRAP", "Error while processing $ETRAP", 0,
"TRACINGON", "Tracing already turned on", 0,
"CITABENV", "Environment variable for call-in table !AD not set", 2,
@@ -941,10 +941,10 @@ LITDEF err_msg merrors[] = {
"INVZDIRFORM", "Invalid value (!UL) specified for ZDIR_FORM", 1,
"ZDIROUTOFSYNC", "$ZDIRECTORY !AD is not the same as its cached value !AD", 4,
"GBLNOEXIST", "Global !AD no longer exists", 2,
- "MAXBTLEVEL", "Global !AD reached maximum level", 2,
+ "MAXBTLEVEL", "Global ^!AD in region !AD reached maximum level", 4,
"INVMNEMCSPC", "Unsupported mnemonicspace !AD", 2,
"JNLALIGNSZCHG", "Journal ALIGNSIZE is rounded up to !UL blocks (closest next higher power of two)", 1,
- "UNUSEDMSG1109", "MAXTRACELEVEL : last used in V5.4-002B", 0,
+ "SEFCTNEEDSFULLB", "Current side effect setting does not permit full Boolean to be turned off", 0,
"GVFAILCORE", "A core file is being created for later analysis if necessary", 0,
"DBCDBNOCERTIFY", "Database !AD HAS NOT been certified due to the preceding errors - rerun DBCERTIFY SCAN", 2,
"DBFRZRESETSUC", "Freeze released successfully on database file !AD", 2,
@@ -1091,7 +1091,7 @@ LITDEF err_msg merrors[] = {
"REPLINSTSTNDALN", "Could not get exclusive access to replication instance file !AD", 2,
"REPLREQROLLBACK", "Replication instance file !AD indicates abnormal shutdown or an incomplete ROLLBACK. Run MUPIP JOURNAL ROLLBACK first", 2,
"REQROLLBACK", "Error accessing database !AD. Run MUPIP JOURNAL ROLLBACK on cluster node !AD.", 4,
- "UNUSEDMSG1256", "REPLUPGRADESEC : Last used in V5.4-002B", 0,
+ "INVOBJFILE", "Cannot ZLINK object file !AD due to unexpected format", 2,
"SRCSRVEXISTS", "Source server for secondary instance !AD is already running with pid !UL", 3,
"SRCSRVNOTEXIST", "Source server for secondary instance !AD is not alive", 2,
"SRCSRVTOOMANY", "Cannot start more than !UL source servers in replication instance !AD", 3,
@@ -1131,7 +1131,7 @@ LITDEF err_msg merrors[] = {
"COMMITWAITSTUCK", "Pid !UL timed out after waiting !UL minute(s) for !UL concurrent GT.M process(es) to finish commits in database file !AD", 5,
"COMMITWAITPID", "Pid !UL waited !UL minute(s) for pid !UL to finish commits to block 0x!XL in database file !AD", 6,
"UPDREPLSTATEOFF", "Error replicating global ^!AD as it maps to database !AD which has replication turned OFF", 4,
- "LITNONGRAPH", "M standard requires graphics in string literals", 0,
+ "LITNONGRAPH", "M standard requires graphics in string literals; found non-printable: $ZCHAR(!AD)", 2,
"DBFHEADERR8", "Database file !AD: control problem: !AD was 0x!16 at XQ expecting 0x!16 at XQ", 6,
"MMBEFOREJNL", "BEFORE image journaling cannot be set with MM access method in database file !AD", 2,
"MMNOBFORRPL", "Replication cannot be used in database file !AD which uses MM access method and NOBEFORE image journaling", 2,
@@ -1252,7 +1252,7 @@ LITDEF err_msg merrors[] = {
"MUUSERECOV", "Abnormal shutdown of journaled database !AD detected", 2,
"SECNOTSUPPLEMENTARY", "!AD is a Supplementary Instance and so cannot act as a source to non-Supplementary Instance !AD ", 4,
"SUPRCVRNEEDSSUPSRC", "Instance !AD is not configured to perform local updates so it cannot act as a receiver for non-Supplementary Instance !AD", 4,
- "UNUSEDMSG1417", "SYNCTOSAMETYPE: Never used before so slot free for reuse", 0,
+ "PEERPIDMISMATCH", "Local socket peer with PID=!UL does not match specified PID=!UL", 2,
"SETITIMERFAILED", "A setitimer() call returned an error status of !UL", 1,
"UPDSYNC2MTINS", "Can only UPDATERESYNC with an empty instance file", 0,
"UPDSYNCINSTFILE", "Error with instance file name specified in UPDATERESYNC qualifier", 0,
@@ -1322,7 +1322,7 @@ LITDEF err_msg merrors[] = {
"JNLBUFFDBUPD", "Journal file buffer size for database file !AD has been adjusted from !UL to !UL.", 4,
"LOCKINCR2HIGH", "Attempt to increment a LOCK more than !UL times", 1,
"LOCKIS", "!_!_Resource name: !AD", 2,
- "LDSPANGLOINCMP", "Incomplete spanning node found during load", 0,
+ "LDSPANGLOINCMP", "Incomplete spanning node found during load!/!_!_at File offset : [0x!16 at XQ]", 1,
"MUFILRNDWNFL2", "Database section (id = !UL) belonging to database file !AD rundown failed", 3,
"MUINSTFROZEN", "!AD : Instance !AZ is frozen. Waiting for instance to be unfrozen before proceeding with writes to database file !AD", 5,
"MUINSTUNFROZEN", "!AD : Instance !AZ is now Unfrozen. Continuing with writes to database file !AD", 5,
@@ -1363,7 +1363,7 @@ LITDEF err_msg merrors[] = {
"INSTFRZDEFER", "Instance Freeze initiated by !AD error on region !AD deferred due to critical resource conflict", 4,
"REGOPENRETRY", "Attempt to open region !AD (!AD) using startup shortcut failed due to conflicting database shutdown. Retrying...", 4,
"REGOPENFAIL", "Failed to open region !AD (!AD) due to conflicting database shutdown activity", 4,
- "REPLINSTNOSHM", "Database !AD has no active connection to a replication journal pool; please verify that the database is listed in your instance file", 2,
+ "REPLINSTNOSHM", "Database !AD has no active connection to a replication journal pool", 2,
"DEVPARMTOOSMALL", "Deviceparameter must be greater than zero (0)", 0,
"REMOTEDBNOSPGBL", "Database region !AD contains portion of a spanning global and so cannot point to a remote file", 2,
"NCTCOLLSPGBL", "Database region !AD contains portion of spanning global ^!AD and so cannot support non-zero numeric collation type", 4,
@@ -1382,6 +1382,33 @@ LITDEF err_msg merrors[] = {
"TLSIOERROR", "Error during TLS/SSL !AD operation", 2,
"TLSRENEGOTIATE", "Failed to renegotiate TLS/SSL connection", 0,
"REPLNOTLS", "!AD requested TLS/SSL communication but the !AD was either not started with TLSID qualifier or does not support TLS/SSL protocol", 4,
+ "COLTRANSSTR2LONG", "Output string after collation transformation is too long", 0,
+ "SOCKPASS", "Socket pass failed", 0,
+ "SOCKACCEPT", "Socket accept failed", 0,
+ "NOSOCKHANDLE", "No socket handle specified in WRITE /PASS", 0,
+ "TRIGLOADFAIL", "MUPIP TRIGGER or $ZTRIGGER operation failed. Failure code: !AD.", 2,
+ "SOCKPASSDATAMIX", "Attempt to use a LOCAL socket for both READ/WRITE and PASS/ACCEPT", 0,
+ "NOGTCMDB", "!AD does not support operation on GT.CM database region: !AD", 4,
+ "NOUSERDB", "!AD does not support operation on non-GDS format region: !AD", 4,
+ "DSENOTOPEN", "DSE could not open region !AD - see DSE startup error message for cause", 2,
+ "ZSOCKETATTR", "Attribute \"!AD\" invalid for $ZSOCKET function", 2,
+ "ZSOCKETNOTSOCK", "$ZSOCKET function called but device is not a socket", 0,
+ "CHSETALREADY", "CHSET !AD already specified for socket device", 2,
+ "DSEMAXBLKSAV", "DSE cannot SAVE another block as it already has the maximum of !UL", 1,
+ "BLKINVALID", "!XL is not a valid block as database file !AD has !XL total blocks", 4,
+ "CANTBITMAP", "Can't perform this operation on a bit map (block at a 200 hexadecimal boundary)", 0,
+ "AIMGBLKFAIL", "After image build for block !XL in region !AD failed in DSE or MUPIP", 3,
+ "GTMDISTUNVERIF", "Environment variable $gtm_dist (!AD) could not be verified against the executables path (!AD)", 4,
+ "CRYPTNOAPPEND", "APPEND disallowed on the encrypted file !AD", 2,
+ "CRYPTNOSEEK", "SEEK disallowed on the encrypted file !AD", 2,
+ "CRYPTNOTRUNC", "Not positioned at file start or EOF. TRUNCATE disallowed on the encrypted file !AD", 2,
+ "CRYPTNOKEYSPEC", "Key name needs to be specified with KEY, IKEY, or OKEY device parameter for encrypted I/O", 0,
+ "CRYPTNOOVERRIDE", "Cannot override IVEC and/or key without compromising integrity", 0,
+ "CRYPTKEYTOOBIG", "Specified key has length !UL, which is greater than the maximum allowed key length !UL", 2,
+ "CRYPTBADWRTPOS", "Encrypted WRITE disallowed from a position different than where the last WRITE completed", 0,
+ "LABELNOTFND", "GOTO referenced a label that does not exist", 0,
+ "RELINKCTLERR", "Error with relink control structure for $ZROUTINES directory !AD", 2,
+ "INVLINKTMPDIR", "Value for $gtm_linktmpdir is either not found or not a directory: !AD", 2,
};
LITDEF int ERR_ACK = 150372361;
@@ -1466,7 +1493,7 @@ LITDEF int ERR_GVSUBOFLOW = 150372986;
LITDEF int ERR_GVUNDEF = 150372994;
LITDEF int ERR_TRANSNEST = 150373002;
LITDEF int ERR_INDEXTRACHARS = 150373010;
-LITDEF int ERR_UNUSEDMSG260 = 150373018;
+LITDEF int ERR_CORRUPTNODE = 150373018;
LITDEF int ERR_INDRMAXLEN = 150373026;
LITDEF int ERR_INSFFBCNT = 150373034;
LITDEF int ERR_INTEGERRS = 150373042;
@@ -2015,7 +2042,7 @@ LITDEF int ERR_MUKILLIP = 150377376;
LITDEF int ERR_JNLRDONLY = 150377386;
LITDEF int ERR_ANCOMPTINC = 150377394;
LITDEF int ERR_ABNCOMPTINC = 150377402;
-LITDEF int ERR_UNUSEDMSG809 = 150377410;
+LITDEF int ERR_RECLOAD = 150377410;
LITDEF int ERR_SOCKNOTFND = 150377418;
LITDEF int ERR_CURRSOCKOFR = 150377426;
LITDEF int ERR_SOCKETEXIST = 150377434;
@@ -2039,7 +2066,7 @@ LITDEF int ERR_TOOMANYCLIENTS = 150377570;
LITDEF int ERR_NOEXCLUDE = 150377579;
LITDEF int ERR_GVINCRISOLATION = 150377586;
LITDEF int ERR_EXCLUDEREORG = 150377592;
-LITDEF int ERR_REORGINC = 150377602;
+LITDEF int ERR_REORGINC = 150377600;
LITDEF int ERR_ASC2EBCDICCONV = 150377610;
LITDEF int ERR_GTMSECSHRSTART = 150377618;
LITDEF int ERR_DBVERPERFWARN1 = 150377624;
@@ -2195,16 +2222,16 @@ LITDEF int ERR_REPLJNLCLOSED = 150378818;
LITDEF int ERR_RENAMEFAIL = 150378824;
LITDEF int ERR_FILERENAME = 150378835;
LITDEF int ERR_JNLBUFINFO = 150378843;
-LITDEF int ERR_UNUSEDMSG989 = 150378850;
-LITDEF int ERR_UNUSEDMSG990 = 150378858;
+LITDEF int ERR_SDSEEKERR = 150378850;
+LITDEF int ERR_LOCALSOCKREQ = 150378858;
LITDEF int ERR_TPNOTACID = 150378867;
LITDEF int ERR_JNLSETDATA2LONG = 150378874;
LITDEF int ERR_JNLNEWREC = 150378882;
LITDEF int ERR_REPLFTOKSEM = 150378890;
-LITDEF int ERR_UNUSEDMSG995 = 150378898;
+LITDEF int ERR_SOCKNOTPASSED = 150378898;
LITDEF int ERR_EXTRIOERR = 150378906;
LITDEF int ERR_EXTRCLOSEERR = 150378914;
-LITDEF int ERR_UNUSEDMSG998 = 150378922;
+LITDEF int ERR_CONNSOCKREQ = 150378922;
LITDEF int ERR_REPLEXITERR = 150378930;
LITDEF int ERR_MUDESTROYSUC = 150378939;
LITDEF int ERR_DBRNDWN = 150378946;
@@ -2285,7 +2312,7 @@ LITDEF int ERR_NOSUBSCRIPT = 150379538;
LITDEF int ERR_SYSTEMVALUE = 150379546;
LITDEF int ERR_SIZENOTVALID4 = 150379554;
LITDEF int ERR_STRNOTVALID = 150379562;
-LITDEF int ERR_UNUSEDMSG1079 = 150379570;
+LITDEF int ERR_CREDNOTPASSED = 150379570;
LITDEF int ERR_ERRWETRAP = 150379578;
LITDEF int ERR_TRACINGON = 150379587;
LITDEF int ERR_CITABENV = 150379594;
@@ -2315,7 +2342,7 @@ LITDEF int ERR_GBLNOEXIST = 150379779;
LITDEF int ERR_MAXBTLEVEL = 150379786;
LITDEF int ERR_INVMNEMCSPC = 150379794;
LITDEF int ERR_JNLALIGNSZCHG = 150379803;
-LITDEF int ERR_UNUSEDMSG1109 = 150379810;
+LITDEF int ERR_SEFCTNEEDSFULLB = 150379810;
LITDEF int ERR_GVFAILCORE = 150379818;
LITDEF int ERR_DBCDBNOCERTIFY = 150379826;
LITDEF int ERR_DBFRZRESETSUC = 150379835;
@@ -2462,7 +2489,7 @@ LITDEF int ERR_REPLINSTSEQORD = 150380954;
LITDEF int ERR_REPLINSTSTNDALN = 150380962;
LITDEF int ERR_REPLREQROLLBACK = 150380970;
LITDEF int ERR_REQROLLBACK = 150380978;
-LITDEF int ERR_UNUSEDMSG1256 = 150380986;
+LITDEF int ERR_INVOBJFILE = 150380986;
LITDEF int ERR_SRCSRVEXISTS = 150380994;
LITDEF int ERR_SRCSRVNOTEXIST = 150381002;
LITDEF int ERR_SRCSRVTOOMANY = 150381010;
@@ -2623,7 +2650,7 @@ LITDEF int ERR_EXTRFILEXISTS = 150382242;
LITDEF int ERR_MUUSERECOV = 150382250;
LITDEF int ERR_SECNOTSUPPLEMENTARY = 150382258;
LITDEF int ERR_SUPRCVRNEEDSSUPSRC = 150382266;
-LITDEF int ERR_UNUSEDMSG1417 = 150382275;
+LITDEF int ERR_PEERPIDMISMATCH = 150382274;
LITDEF int ERR_SETITIMERFAILED = 150382284;
LITDEF int ERR_UPDSYNC2MTINS = 150382290;
LITDEF int ERR_UPDSYNCINSTFILE = 150382298;
@@ -2753,9 +2780,36 @@ LITDEF int ERR_TLSCONNINFO = 150383280;
LITDEF int ERR_TLSIOERROR = 150383290;
LITDEF int ERR_TLSRENEGOTIATE = 150383298;
LITDEF int ERR_REPLNOTLS = 150383306;
+LITDEF int ERR_COLTRANSSTR2LONG = 150383314;
+LITDEF int ERR_SOCKPASS = 150383322;
+LITDEF int ERR_SOCKACCEPT = 150383330;
+LITDEF int ERR_NOSOCKHANDLE = 150383338;
+LITDEF int ERR_TRIGLOADFAIL = 150383346;
+LITDEF int ERR_SOCKPASSDATAMIX = 150383354;
+LITDEF int ERR_NOGTCMDB = 150383362;
+LITDEF int ERR_NOUSERDB = 150383370;
+LITDEF int ERR_DSENOTOPEN = 150383378;
+LITDEF int ERR_ZSOCKETATTR = 150383386;
+LITDEF int ERR_ZSOCKETNOTSOCK = 150383394;
+LITDEF int ERR_CHSETALREADY = 150383402;
+LITDEF int ERR_DSEMAXBLKSAV = 150383410;
+LITDEF int ERR_BLKINVALID = 150383418;
+LITDEF int ERR_CANTBITMAP = 150383426;
+LITDEF int ERR_AIMGBLKFAIL = 150383434;
+LITDEF int ERR_GTMDISTUNVERIF = 150383442;
+LITDEF int ERR_CRYPTNOAPPEND = 150383450;
+LITDEF int ERR_CRYPTNOSEEK = 150383458;
+LITDEF int ERR_CRYPTNOTRUNC = 150383466;
+LITDEF int ERR_CRYPTNOKEYSPEC = 150383474;
+LITDEF int ERR_CRYPTNOOVERRIDE = 150383482;
+LITDEF int ERR_CRYPTKEYTOOBIG = 150383490;
+LITDEF int ERR_CRYPTBADWRTPOS = 150383498;
+LITDEF int ERR_LABELNOTFND = 150383506;
+LITDEF int ERR_RELINKCTLERR = 150383514;
+LITDEF int ERR_INVLINKTMPDIR = 150383522;
GBLDEF err_ctl merrors_ctl = {
246,
"GTM",
&merrors[0],
- 1369};
+ 1396};
diff --git a/sr_x86_64/obj_filesp.c b/sr_x86_64/obj_filesp.c
index bca0a2a..5366dfd 100644
--- a/sr_x86_64/obj_filesp.c
+++ b/sr_x86_64/obj_filesp.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2007, 2010 Fidelity Information Services, Inc *
+ * Copyright 2007, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -30,12 +30,12 @@
#include "mdef.h"
-#include "gtm_string.h"
#include <errno.h>
#include <libelf.h>
#include "gtm_fcntl.h"
#include "gtm_unistd.h"
#include "gtm_stdio.h"
+#include "gtm_string.h"
#include "compiler.h"
#include <rtnhdr.h>
@@ -52,8 +52,8 @@
#include <obj_filesp.h>
#include "release_name.h"
#include "min_max.h"
-/* The following definitions are reqquired for the new(for ELF files) create/close_obj_file.c functions */
+/* The following definitions are required for the new(for ELF files) create/close_obj_file.c functions */
#ifdef __linux__
#define ELF64_LINKER_FLAG 0x10
#else
@@ -61,9 +61,7 @@
#endif /* __linux__ */
-/* Platform specific action instructions when routine called from foreign language */
-/* Currently just a return to caller on AIX */
-
+/* Platform specific action instructions when routine called from foreign language. Returns -1 to caller */
#define MIN_LINK_PSECT_SIZE 0
LITDEF mach_inst jsb_action[JSB_ACTION_N_INS] = {0x48, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xc3};
@@ -117,55 +115,24 @@ error_def(ERR_OBJFILERR);
/* Open the object file and write out the gtm object. Actual ELF creation happens at later stage during close_object_file */
void create_object_file(rhdtyp *rhead)
{
- int status, rout_len;
- char obj_name[SIZEOF(mident_fixed) + 5];
- mstr fstr;
- parse_blk pblk;
-
- error_def(ERR_FILEPARSE);
-
assert(!run_time);
-
DEBUG_ONLY(obj_bytes_written = 0);
- memset(&pblk, 0, SIZEOF(pblk));
- pblk.buffer = object_file_name;
- pblk.buff_size = MAX_FBUFF;
-
- /* create the object file */
- fstr.len = (MV_DEFINED(&cmd_qlf.object_file) ? cmd_qlf.object_file.str.len : 0);
- fstr.addr = cmd_qlf.object_file.str.addr;
- rout_len = (int)module_name.len;
- memcpy(&obj_name[0], module_name.addr, rout_len);
- memcpy(&obj_name[rout_len], DOTOBJ, SIZEOF(DOTOBJ)); /* includes null terminator */
- pblk.def1_size = rout_len + SIZEOF(DOTOBJ) - 1; /* Length does not include null terminator */
- pblk.def1_buf = obj_name;
- status = parse_file(&fstr, &pblk);
- if (0 == (status & 1))
- rts_error(VARLSTCNT(5) ERR_FILEPARSE, 2, fstr.len, fstr.addr, status);
-
- object_name_len = pblk.b_esl;
- object_file_name[object_name_len] = 0;
-
- OPEN_OBJECT_FILE(object_file_name, O_CREAT | O_RDWR, object_file_des);
- if (FD_INVALID == object_file_des)
- rts_error(VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
-
-/* Action instructions and marker are not kept in the same array since the type of the elements of
- * the former (uint4) may be different from the type of the elements of the latter (char).
- * 'tiz cleaner this way rather than converting one to the other type in order to be accommodated
- * in an array
- * */
- assert(JSB_ACTION_N_INS * SIZEOF(jsb_action[0]) == SIZEOF(jsb_action)); /* JSB_ACTION_N_INS maintained? */
- assert(SIZEOF(jsb_action) <= SIZEOF(rhead->jsb)); /* overflow check */
-
- memcpy(rhead->jsb, (char *)jsb_action, SIZEOF(jsb_action)); /* action instructions */
- memcpy(&rhead->jsb[SIZEOF(jsb_action)], JSB_MARKER, /* followed by GTM_CODE marker */
+ init_object_file_name(); /* inputs: cmd_qlf.object_file, module_name; outputs: object_file_name, object_name_len */
+ object_file_des = mk_tmp_object_file(object_file_name, object_name_len);
+ /* Action instructions and marker are not kept in the same array since the type of the elements of
+ * the former (uint4) may be different from the type of the elements of the latter (char).
+ * 'tiz cleaner this way rather than converting one to the other type in order to be accommodated
+ * in an array
+ */
+ assert(JSB_ACTION_N_INS * SIZEOF(jsb_action[0]) == SIZEOF(jsb_action)); /* JSB_ACTION_N_INS maintained? */
+ assert(SIZEOF(jsb_action) <= SIZEOF(rhead->jsb)); /* Overflow check */
+
+ memcpy(rhead->jsb, (char *)jsb_action, SIZEOF(jsb_action)); /* Action instructions */
+ memcpy(&rhead->jsb[SIZEOF(jsb_action)], JSB_MARKER, /* Followed by GTM_CODE marker */
MIN(STR_LIT_LEN(JSB_MARKER), SIZEOF(rhead->jsb) - SIZEOF(jsb_action)));
-
emit_immed((char *)rhead, SIZEOF(*rhead));
}
-
/* At this point, we know only gtm_object has been written onto the file.
* Read that gtm_object and wrap it up in .text section, add remaining sections to native object(ELF)
* Update the ELF, write it out to the object file and close the object file */
@@ -188,135 +155,116 @@ void close_object_file(void)
actualSize = 0;
string_tbl = malloc(SPACE_STRING_ALLOC_LEN);
symIndex = 0;
-
strEntrySize = SIZEOF(static_string_tbl);
memcpy((string_tbl + symIndex), static_string_tbl, strEntrySize);
symIndex += strEntrySize;
-
strEntrySize = SIZEOF(GTM_LANG);
memcpy((string_tbl + symIndex), GTM_LANG, strEntrySize);
symIndex += strEntrySize;
-
strEntrySize = SIZEOF(GTM_PRODUCT);
memcpy((string_tbl + symIndex), GTM_PRODUCT, strEntrySize);
symIndex += strEntrySize;
-
strEntrySize = SIZEOF(GTM_RELEASE_NAME);
memcpy((string_tbl + symIndex), GTM_RELEASE_NAME, strEntrySize);
- symIndex += strEntrySize;
-
+ symIndex += strEntrySize;
gtm_obj_code = (char *)malloc(bufSize);
/* At this point, we have only the GTM object written onto the file.
* We need to read it back and wrap inside the ELF object and
- * write a native ELF object file. */
+ * write a native ELF object file.
+ */
lseek(object_file_des, 0, SEEK_SET);
DOREADRL(object_file_des, gtm_obj_code, bufSize, actualSize);
/* Reset the pointer back for writing an ELF object. */
lseek(object_file_des, 0, SEEK_SET);
-
/* Generate ELF64 header */
- if (elf_version(EV_CURRENT) == EV_NONE )
+ if (EV_NONE == elf_version(EV_CURRENT))
{
- FPRINTF(stderr, "Elf library out of date!n");
- GTMASSERT;
+ FPRINTF(stderr, "Elf library out of date!\n");
+ assertpro(FALSE);
}
- if ((elf = elf_begin(object_file_des, ELF_C_WRITE, NULL)) == 0)
+ if (0 == (elf = elf_begin(object_file_des, ELF_C_WRITE, NULL)))
{
FPRINTF(stderr, "elf_begin failed!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
- if ( (ehdr = elf64_newehdr(elf)) == NULL )
+ if (NULL == (ehdr = elf64_newehdr(elf)))
{
FPRINTF(stderr, "elf64_newehdr() failed!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
ehdr->e_ident[EI_MAG0] = ELFMAG0;
ehdr->e_ident[EI_MAG1] = ELFMAG1;
ehdr->e_ident[EI_MAG2] = ELFMAG2;
ehdr->e_ident[EI_MAG3] = ELFMAG3;
ehdr->e_ident[EI_CLASS] = ELFCLASS64;
ehdr->e_ident[EI_VERSION] = EV_CURRENT;
-#ifdef __hpux
+# ifdef __hpux
ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
ehdr->e_ident[EI_OSABI] = ELFOSABI_HPUX;
-#else
+# else
ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
ehdr->e_ident[EI_OSABI] = ELFOSABI_LINUX;
-#endif /* __hpux */
+# endif /* __hpux */
ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT;
ehdr->e_machine = EM_X86_64;
ehdr->e_type = ET_REL;
ehdr->e_version = EV_CURRENT;
ehdr->e_shoff = SIZEOF(Elf64_Ehdr);
ehdr->e_flags = ELF64_LINKER_FLAG;
-
- if ((text_scn = elf_newscn(elf)) == NULL)
+ if (NULL == (text_scn = elf_newscn(elf)))
{
FPRINTF(stderr, "elf_newscn() failed for text section!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
- if ((text_data = elf_newdata(text_scn)) == NULL)
+ if (NULL == (text_data = elf_newdata(text_scn)))
{
FPRINTF(stderr, "elf_newdata() failed for text section!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
text_data->d_align = SECTION_ALIGN_BOUNDARY;
text_data->d_off = 0LL;
text_data->d_buf = gtm_obj_code;
text_data->d_type = ELF_T_REL;
text_data->d_size = gtm_object_size;
text_data->d_version = EV_CURRENT;
-
- if ((text_shdr = elf64_getshdr(text_scn)) == NULL)
+ if (NULL == (text_shdr = elf64_getshdr(text_scn)))
{
FPRINTF(stderr, "elf64_getshdr() failed for text section\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
text_shdr->sh_name = STR_SEC_TEXT_OFFSET;
text_shdr->sh_type = SHT_PROGBITS;
text_shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
text_shdr->sh_entsize = gtm_object_size;
-
memcpy((string_tbl + symIndex), module_name.addr, module_name.len);
string_tbl[symIndex + module_name.len] = '\0';
-
- if ((strtab_scn = elf_newscn(elf)) == NULL)
+ if (NULL == (strtab_scn = elf_newscn(elf)))
{
FPRINTF(stderr, "elf_newscn() failed for strtab section\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
- if ((strtab_data = elf_newdata(strtab_scn)) == NULL)
+ if (NULL == (strtab_data = elf_newdata(strtab_scn)))
{
FPRINTF(stderr, "elf_newdata() failed for strtab section!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
strtab_data->d_align = NATIVE_WSIZE;
strtab_data->d_buf = string_tbl;
strtab_data->d_off = 0LL;
strtab_data->d_size = SPACE_STRING_ALLOC_LEN;
strtab_data->d_type = ELF_T_BYTE;
strtab_data->d_version = EV_CURRENT;
-
- if ((strtab_shdr = elf64_getshdr(strtab_scn)) == NULL)
+ if (NULL == (strtab_shdr = elf64_getshdr(strtab_scn)))
{
FPRINTF(stderr, "elf_getshdr() failed for strtab section!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
strtab_shdr->sh_name = STR_SEC_STRTAB_OFFSET;
strtab_shdr->sh_type = SHT_STRTAB;
strtab_shdr->sh_entsize = 0;
ehdr->e_shstrndx = elf_ndxscn(strtab_scn);
-
/* Creating .symbtab section */
i = 0;
-
/* NULL symbol */
symEntries[i].st_name = 0;
symEntries[i].st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE);
@@ -325,7 +273,6 @@ void close_object_file(void)
symEntries[i].st_size = 0;
symEntries[i].st_value = 0;
i++;
-
/* Module symbol */
symEntries[i].st_name = symIndex;
symEntries[i].st_info = ELF64_ST_INFO(STB_GLOBAL, STT_FUNC);
@@ -334,7 +281,6 @@ void close_object_file(void)
symEntries[i].st_size = gtm_object_size;
symEntries[i].st_value = 0;
i++;
-
/* symbol for .text section */
symEntries[i].st_name = STR_SEC_TEXT_OFFSET;
symEntries[i].st_info = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
@@ -343,51 +289,42 @@ void close_object_file(void)
symEntries[i].st_size = 0;
symEntries[i].st_value = 0;
i++;
-
- if ((symtab_scn = elf_newscn(elf)) == NULL)
+ if (NULL == (symtab_scn = elf_newscn(elf)))
{
FPRINTF(stderr, "elf_newscn() failed for symtab section!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
- if ((symtab_data = elf_newdata(symtab_scn)) == NULL)
+ if (NULL == (symtab_data = elf_newdata(symtab_scn)))
{
FPRINTF(stderr, "elf_newdata() failed for symtab section!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
symtab_data->d_align = NATIVE_WSIZE;
symtab_data->d_off = 0LL;
symtab_data->d_buf = symEntries;
symtab_data->d_type = ELF_T_REL;
symtab_data->d_size = SIZEOF(Elf64_Sym) * i;
symtab_data->d_version = EV_CURRENT;
-
- if ((symtab_shdr = elf64_getshdr(symtab_scn)) == NULL)
+ if (NULL == (symtab_shdr = elf64_getshdr(symtab_scn)))
{
FPRINTF(stderr, "elf_getshdr() failed for symtab section!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
symtab_shdr->sh_name = STR_SEC_SYMTAB_OFFSET;
symtab_shdr->sh_type = SHT_SYMTAB;
symtab_shdr->sh_entsize = SIZEOF(Elf64_Sym) ;
symtab_shdr->sh_link = SEC_STRTAB_INDX;
-
elf_flagehdr(elf, ELF_C_SET, ELF_F_DIRTY);
- if (elf_update(elf, ELF_C_WRITE) < 0)
+ if (0 > elf_update(elf, ELF_C_WRITE))
{
FPRINTF(stderr, "elf_update() failed!\n");
- GTMASSERT;
+ assertpro(FALSE);
}
-
elf_end(elf);
-
/* Free the memory malloc'ed above */
free(string_tbl);
free(gtm_obj_code);
-
if ((off_t)-1 == lseek(object_file_des, (off_t)0, SEEK_SET))
- rts_error(VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
+ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_OBJFILERR, 2, object_name_len, object_file_name, errno);
}
diff --git a/sr_x86_64/op_extjmp.s b/sr_x86_64/op_extjmp.s
index 4f0f8a8..8bd4b39 100644
--- a/sr_x86_64/op_extjmp.s
+++ b/sr_x86_64/op_extjmp.s
@@ -1,6 +1,6 @@
#################################################################
# #
-# Copyright 2007, 2010 Fidelity Information Services, Inc #
+# Copyright 2007, 2014 Fidelity Information Services, Inc #
# #
# This source code contains the intellectual property #
# of its copyright holder(s), and is made available #
@@ -22,7 +22,7 @@
# PAGE +
.DATA
.extern ERR_GTMCHECK
-.extern ERR_LABELUNKNOWN
+.extern ERR_LABELNOTFND
.extern frame_pointer
.text
@@ -86,7 +86,7 @@ l3: movl ERR_GTMCHECK(REG_IP),REG32_ARG1
getframe
ret
-l4: movl ERR_LABELUNKNOWN(REG_IP),REG32_ARG1
+l4: movl ERR_LABELNOTFND(REG_IP),REG32_ARG1
movl $1,REG32_ARG0
movb $0,REG8_ACCUM # variable length argument
call rts_error
diff --git a/sr_x86_64/opp_setzbrk.s b/sr_x86_64/opp_setzbrk.s
new file mode 100644
index 0000000..8a34979
--- /dev/null
+++ b/sr_x86_64/opp_setzbrk.s
@@ -0,0 +1,38 @@
+#################################################################
+# #
+# Copyright 2013, 2014 Fidelity Information Services, Inc #
+# #
+# This source code contains the intellectual property #
+# of its copyright holder(s), and is made available #
+# under a license. If you do not know the terms of #
+# the license, please stop and do not read further. #
+# #
+#################################################################
+
+# PAGE ,132
+ .title opp_setzbrk.s
+
+# .386
+# .MODEL FLAT, C
+
+.include "linkage.si"
+ .INCLUDE "g_msf.si"
+
+ .sbttl opp_setzbrk
+# PAGE +
+ .DATA
+.extern frame_pointer
+
+ .text
+.extern op_setzbrk
+
+# PUBLIC opp_setzbrk
+ENTRY opp_setzbrk
+ putframe
+ addq $8,REG_SP # burn return PC
+ call op_setzbrk
+ getframe
+ ret
+# opp_setzbrk ENDP
+
+# END
diff --git a/sr_x86_64/ttt.c b/sr_x86_64/ttt.c
index c85f77d..3f8de37 100644
--- a/sr_x86_64/ttt.c
+++ b/sr_x86_64/ttt.c
@@ -1,6 +1,6 @@
/****************************************************************
* *
- * Copyright 2001, 2013 Fidelity Information Services, Inc *
+ * Copyright 2001, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
@@ -13,696 +13,709 @@
#include "vxi.h"
#include "vxt.h"
#include "xfer_enum.h"
-LITDEF short ttt[4305] = {
+LITDEF short ttt[4378] = {
-/* 0 */ 0,0,0,0,325,3561,3032,567,
-/* 8 */ 2356,3017,3047,2028,421,3511,2149,3135,
-/* 16 */ 2232,2220,3744,3781,2193,2202,2274,2214,
-/* 24 */ 2265,2244,2172,773,788,800,812,854,
-/* 32 */ 872,893,922,952,967,982,1000,1159,
-/* 40 */ 1072,1105,1138,1216,1267,1597,1630,1645,
-/* 48 */ 1675,1741,1771,1795,1858,1879,1894,3576,
-/* 56 */ 3598,0,0,0,0,582,0,523,
-/* 64 */ 0,2014,0,3121,0,0,0,0,
-/* 72 */ 0,0,357,433,2334,2340,2765,2792,
-/* 80 */ 2810,2913,2851,2842,2928,3650,3734,3068,
-/* 88 */ 0,3100,3201,3164,3149,3179,3525,3377,
-/* 96 */ 3656,3668,3683,3707,3716,3701,3692,3410,
-/* 104 */ 3777,3790,3812,3849,3861,3882,3906,3972,
-/* 112 */ 0,0,2961,2316,3253,4254,661,4257,
-/* 120 */ 715,2822,3219,537,543,4260,2419,2516,
-/* 128 */ 2406,490,2442,2536,2181,2474,2546,4263,
-/* 136 */ 2301,2292,4267,1285,4268,353,349,3401,
-/* 144 */ 445,4272,4275,4278,3086,4281,4284,4287,
-/* 152 */ 4290,4293,4296,3547,0,2937,2605,2583,
-/* 160 */ 1558,2574,2352,2163,2888,2049,740,2878,
-/* 168 */ 0,0,2371,3725,3753,1489,3677,2454,
-/* 176 */ 2042,552,3873,1843,2283,1201,340,3205,
-/* 184 */ 624,693,605,671,3837,1120,3805,3061,
-/* 192 */ 2310,2952,3075,643,1012,2892,4299,2526,
-/* 200 */ 3924,3942,3957,514,2907,3197,1975,3999,
-/* 208 */ 3984,1303,3539,596,1660,1729,2489,4302,
-/* 216 */ 3610,2562,749,830,3236,3765,3634,3620,
-/* 224 */ 3627,3616,725,907,2429,1054,2393,1042,
-/* 232 */ 2253,1027,1087,2501,1459,1402,1387,1441,
-/* 240 */ 1357,1369,1414,1342,1426,1474,0,3497,
-/* 248 */ 0,931,940,3356,1870,3335,2380,2464,
-/* 256 */ 2987,2993,3005,2973,1240,1252,1174,1186,
-/* 264 */ 1228,3588,1705,1906,0,1315,1501,1579,
-/* 272 */ 3431,1612,1690,1717,1828,1807,3473,1753,
-/* 280 */ 3452,1939,1513,1528,2002,4014,1921,3263,
-/* 288 */ 3275,3287,3299,2801,2816,1546,454,1330,
-/* 296 */ 1957,652,3311,3323,3993,4005,0,0,
-/* 304 */ 0,0,3828,4026,4037,4049,4058,4072,
-/* 312 */ 4085,4095,4112,4124,4133,4145,4157,4169,
-/* 320 */ 4184,4196,4205,4217,4233,VXI_PUSHAB,VXT_VAL,0,
-/* 328 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 336 */ 3,VXT_XFER,SIZEOF(char *) * (short int)xf_add,VXT_END,
-/* 340 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_bindparm,
-/* 348 */ VXT_END,
-/* 349 */ VXI_INCL,VXT_VAL,1,VXT_END,
-/* 353 */ VXI_CLRL,VXT_VAL,0,VXT_END,
-/* 357 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_break,VXT_END,
-/* 361 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callb,VXI_BRB,VXT_JMP,
-/* 369 */ 1,VXT_END,
-/* 371 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_calll,VXI_JMP,VXT_JMP,
-/* 379 */ 1,VXT_END,
-/* 381 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callw,VXI_BRW,VXT_JMP,
-/* 389 */ 1,VXT_END,
-/* 391 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspb,VXI_BRB,VXT_JMP,
-/* 399 */ 1,VXT_END,
-/* 401 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspl,VXI_JMP,VXT_JMP,
-/* 409 */ 1,VXT_END,
-/* 411 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspw,VXI_BRW,VXT_JMP,
-/* 419 */ 1,VXT_END,
-/* 421 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 429 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_cat,VXT_END,
-/* 433 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 441 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_close,VXT_END,
-/* 445 */ VXI_BICB2,VXT_LIT,1,VXT_REG,0x5A,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_dt_false,
-/* 453 */ VXT_END,
-/* 454 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_clralsvars,
-/* 462 */ VXT_END,
-/* 463 */ VXI_TSTL,VXT_VAL,1,VXT_END,
-/* 467 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2bool,
-/* 475 */ VXT_END,
-/* 476 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2mint,
-/* 484 */ VXI_MOVL,VXT_REG,0x50,VXT_VAL,0,VXT_END,
-/* 490 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 498 */ SIZEOF(char *) * (short int)xf_commarg,VXT_END,
-/* 500 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVL,VXT_VAL,1,
-/* 508 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mint2mval,VXT_END,
-/* 514 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2num,
-/* 522 */ VXT_END,
-/* 523 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 531 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_contain,VXT_END,
-/* 537 */ VXI_MOVL,VXT_REG,0x6C,VXT_ADDR,0,VXT_END,
-/* 543 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_currtn,
-/* 551 */ VXT_END,
-/* 552 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 560 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_cvtparm,VXT_END,
-/* 567 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 575 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_div,VXT_END,
-/* 582 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
-/* 590 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equ,VXT_END,
-/* 596 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equnul,
-/* 604 */ VXT_END,
-/* 605 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 613 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_LIT,0,VXI_JSB,
-/* 621 */ VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
-/* 624 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 632 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_JSB,
-/* 640 */ VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
-/* 643 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunret,
-/* 651 */ VXT_END,
-/* 652 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunretals,
-/* 660 */ VXT_END,
-/* 661 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 669 */ SIZEOF(char *) * (short int)xf_extcall,VXT_END,
-/* 671 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 679 */ 3,VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 687 */ VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
-/* 693 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 701 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 709 */ VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
-/* 715 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 723 */ SIZEOF(char *) * (short int)xf_extjmp,VXT_END,
-/* 725 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 733 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_exp,VXT_END,
-/* 740 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fetch,
-/* 748 */ VXT_END,
-/* 749 */ VXT_IREPAB,VXT_VAL,6,VXI_PUSHL,VXT_VAL,5,VXI_PUSHL,VXT_VAL,
-/* 757 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,
-/* 765 */ VXT_LIT,0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
-/* 773 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 781 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnascii,VXT_END,
-/* 788 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 796 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnchar,VXT_END,
-/* 800 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 808 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fndata,VXT_END,
-/* 812 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 820 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 828 */ SIZEOF(char *) * (short int)xf_fnextract,VXT_END,
-/* 830 */ VXT_IREPAB,VXT_VAL,6,VXI_PUSHL,VXT_VAL,5,VXI_PUSHL,VXT_VAL,
-/* 838 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 846 */ VXT_VAL,0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
-/* 854 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 862 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 870 */ SIZEOF(char *) * (short int)xf_fnfind,VXT_END,
-/* 872 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 880 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 888 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfnumber,VXT_END,
-/* 893 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
-/* 901 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget,VXT_END,
-/* 907 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 915 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget2,VXT_END,
-/* 922 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget,
-/* 930 */ VXT_END,
-/* 931 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget1,
-/* 939 */ VXT_END,
-/* 940 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 948 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget1,VXT_END,
-/* 952 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 960 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnincr,VXT_END,
-/* 967 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 975 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnj2,VXT_END,
-/* 982 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 990 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 998 */ SIZEOF(char *) * (short int)xf_fnj3,VXT_END,
-/* 1000 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1008 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlength,VXT_END,
-/* 1012 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1020 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvname,VXT_END,
-/* 1027 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
-/* 1035 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvnameo2,VXT_END,
-/* 1042 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1050 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvprvname,VXT_END,
-/* 1054 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 1062 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,2,VXT_XFER,
-/* 1070 */ SIZEOF(char *) * (short int)xf_fnname,VXT_END,
-/* 1072 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1080 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnnext,VXT_END,
-/* 1087 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
-/* 1095 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1103 */ SIZEOF(char *) * (short int)xf_fno2,VXT_END,
-/* 1105 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1113 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnorder,VXT_END,
-/* 1120 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1128 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1136 */ SIZEOF(char *) * (short int)xf_fnp1,VXT_END,
-/* 1138 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 1146 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1154 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpiece,VXT_END,
-/* 1159 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1167 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpopulation,VXT_END,
-/* 1174 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1182 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqlength,VXT_END,
-/* 1186 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1194 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqsubscript,VXT_END,
-/* 1201 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1209 */ 0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnquery,VXT_END,
-/* 1216 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1224 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnrandom,VXT_END,
-/* 1228 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1236 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnreverse,VXT_END,
-/* 1240 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1248 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack1,VXT_END,
-/* 1252 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1260 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack2,VXT_END,
-/* 1267 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1275 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1283 */ SIZEOF(char *) * (short int)xf_fntext,VXT_END,
-/* 1285 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1293 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1301 */ SIZEOF(char *) * (short int)xf_fntranslate,VXT_END,
-/* 1303 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 1311 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnview,VXT_END,
-/* 1315 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 1323 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzascii,VXT_END,
-/* 1330 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1338 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzahandle,VXT_END,
-/* 1342 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1350 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitand,VXT_END,
-/* 1357 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1365 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitcoun,VXT_END,
-/* 1369 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1377 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1385 */ SIZEOF(char *) * (short int)xf_fnzbitfind,VXT_END,
-/* 1387 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1395 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitget,VXT_END,
-/* 1402 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1410 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitlen,VXT_END,
-/* 1414 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 1422 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitnot,VXT_END,
-/* 1426 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1434 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitor,VXT_END,
-/* 1441 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1449 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1457 */ SIZEOF(char *) * (short int)xf_fnzbitset,VXT_END,
-/* 1459 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1467 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitstr,VXT_END,
-/* 1474 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 1482 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitxor,VXT_END,
-/* 1489 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 1497 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzcall,VXT_END,
-/* 1501 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
-/* 1509 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzchar,VXT_END,
-/* 1513 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1521 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzconvert2,VXT_END,
-/* 1528 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1536 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1544 */ SIZEOF(char *) * (short int)xf_fnzconvert3,VXT_END,
-/* 1546 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1554 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdata,VXT_END,
-/* 1558 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
-/* 1566 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1574 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdate,VXT_END,
-/* 1579 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
-/* 1587 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1595 */ SIZEOF(char *) * (short int)xf_fnzextract,VXT_END,
-/* 1597 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1605 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzfile,VXT_END,
-/* 1612 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1620 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1628 */ SIZEOF(char *) * (short int)xf_fnzfind,VXT_END,
-/* 1630 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1638 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetdvi,VXT_END,
-/* 1645 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1653 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetjpi,VXT_END,
-/* 1660 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1668 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetlki,VXT_END,
-/* 1675 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1683 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetsyi,VXT_END,
-/* 1690 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1698 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzj2,VXT_END,
-/* 1705 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1713 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzjobexam,VXT_END,
-/* 1717 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1725 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlength,VXT_END,
-/* 1729 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1737 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlkid,VXT_END,
-/* 1741 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1749 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzm,VXT_END,
-/* 1753 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1761 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1769 */ SIZEOF(char *) * (short int)xf_fnzp1,VXT_END,
-/* 1771 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
-/* 1779 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 1787 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzparse,VXT_END,
-/* 1795 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1803 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpid,VXT_END,
-/* 1807 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 1815 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 1823 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpiece,VXT_END,
-/* 1828 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1836 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpopulation,VXT_END,
-/* 1843 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1851 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzprevious,VXT_END,
-/* 1858 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1866 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpriv,VXT_END,
-/* 1870 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzqgblmod,
-/* 1878 */ VXT_END,
-/* 1879 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 1887 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsearch,VXT_END,
-/* 1894 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 1902 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsetprv,VXT_END,
-/* 1906 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 1914 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsigproc,VXT_END,
-/* 1921 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 1929 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1937 */ SIZEOF(char *) * (short int)xf_fnzsubstr,VXT_END,
-/* 1939 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1947 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1955 */ SIZEOF(char *) * (short int)xf_fnztranslate,VXT_END,
-/* 1957 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 1965 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
-/* 1973 */ SIZEOF(char *) * (short int)xf_fnztrigger,VXT_END,
-/* 1975 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,6,VXI_PUSHAB,VXT_VAL,
-/* 1983 */ 5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,
-/* 1991 */ VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,7,
-/* 1999 */ VXT_XFER,SIZEOF(char *) * (short int)xf_fnztrnlnm,VXT_END,
-/* 2002 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 2010 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwidth,VXT_END,
-/* 2014 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 2022 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_follow,VXT_END,
-/* 2028 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
-/* 2036 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forcenum,VXT_END,
-/* 2042 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forchk1,VXT_END,
-/* 2049 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2057 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forinit,VXT_END,
-/* 2062 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldob,VXI_BRB,VXT_JMP,
-/* 2070 */ 1,VXT_END,
-/* 2072 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldol,VXI_JMP,VXT_JMP,
-/* 2080 */ 1,VXT_END,
-/* 2082 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldow,VXI_BRW,VXT_JMP,
+/* 0 */ 0,0,0,0,330,3579,3052,572,
+/* 8 */ 2376,3037,3067,2048,426,3529,2169,3155,
+/* 16 */ 2252,2240,3762,3799,2213,2222,2294,2234,
+/* 24 */ 2285,2264,2192,778,793,805,817,859,
+/* 32 */ 877,898,927,957,972,987,1005,1164,
+/* 40 */ 1077,1110,1143,1221,1272,1602,1635,1650,
+/* 48 */ 1680,1746,1776,1800,1863,1884,1902,3594,
+/* 56 */ 3616,0,0,0,0,587,0,528,
+/* 64 */ 0,2034,0,3141,0,0,0,0,
+/* 72 */ 0,0,362,438,2354,2360,2785,2812,
+/* 80 */ 2830,2933,2871,2862,2948,3668,3752,3088,
+/* 88 */ 0,3120,3221,3184,3169,3199,3543,3397,
+/* 96 */ 3674,3686,3701,3725,3734,3719,3710,3430,
+/* 104 */ 3795,3808,3830,3867,3879,3900,3924,3990,
+/* 112 */ 0,0,2981,2336,3273,4327,666,4330,
+/* 120 */ 720,2842,3239,542,548,4333,2439,2536,
+/* 128 */ 2426,495,2462,2556,2201,2494,2566,4336,
+/* 136 */ 2321,2312,4340,1290,4341,358,354,3421,
+/* 144 */ 450,4345,4348,4351,3106,4354,4357,4360,
+/* 152 */ 4363,4366,4369,3565,0,2957,2625,2603,
+/* 160 */ 1563,2594,2372,2183,2908,2069,745,2898,
+/* 168 */ 0,0,2391,3743,3771,1494,3695,2474,
+/* 176 */ 2062,557,3891,1848,2303,1206,345,3225,
+/* 184 */ 629,698,610,676,3855,1125,3823,3081,
+/* 192 */ 2330,2972,3095,648,1017,2912,4372,2546,
+/* 200 */ 3942,3960,3975,519,2927,3217,1995,4017,
+/* 208 */ 4002,1308,3557,601,1665,1734,2509,4375,
+/* 216 */ 3628,2582,754,835,3256,3783,3652,3638,
+/* 224 */ 3645,3634,730,912,2449,1059,2413,1047,
+/* 232 */ 2273,1032,1092,2521,1464,1407,1392,1446,
+/* 240 */ 1362,1374,1419,1347,1431,1479,0,3515,
+/* 248 */ 0,936,945,3376,1875,3355,2400,2484,
+/* 256 */ 3007,3013,3025,2993,1245,1257,1179,1191,
+/* 264 */ 1233,3606,1710,1914,0,1320,1506,1584,
+/* 272 */ 3449,1617,1695,1722,1833,1812,3491,1758,
+/* 280 */ 3470,1959,1518,1533,2022,4032,1941,3283,
+/* 288 */ 3295,3307,3319,2821,2836,1551,459,1335,
+/* 296 */ 1977,657,3331,3343,4011,4023,0,0,
+/* 304 */ 0,0,3846,4044,4055,4067,4076,4090,
+/* 312 */ 4103,4113,4130,4142,4151,4163,4175,4187,
+/* 320 */ 4202,4214,4223,4235,4251,1929,4272,4284,
+/* 328 */ 4307,4318,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,
+/* 336 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_add,
+/* 344 */ VXT_END,
+/* 345 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_bindparm,
+/* 353 */ VXT_END,
+/* 354 */ VXI_INCL,VXT_VAL,1,VXT_END,
+/* 358 */ VXI_CLRL,VXT_VAL,0,VXT_END,
+/* 362 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_break,VXT_END,
+/* 366 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callb,VXI_BRB,VXT_JMP,
+/* 374 */ 1,VXT_END,
+/* 376 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_calll,VXI_JMP,VXT_JMP,
+/* 384 */ 1,VXT_END,
+/* 386 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callw,VXI_BRW,VXT_JMP,
+/* 394 */ 1,VXT_END,
+/* 396 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspb,VXI_BRB,VXT_JMP,
+/* 404 */ 1,VXT_END,
+/* 406 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspl,VXI_JMP,VXT_JMP,
+/* 414 */ 1,VXT_END,
+/* 416 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_callspw,VXI_BRW,VXT_JMP,
+/* 424 */ 1,VXT_END,
+/* 426 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 434 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_cat,VXT_END,
+/* 438 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 446 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_close,VXT_END,
+/* 450 */ VXI_BICB2,VXT_LIT,1,VXT_REG,0x5A,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_dt_false,
+/* 458 */ VXT_END,
+/* 459 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_clralsvars,
+/* 467 */ VXT_END,
+/* 468 */ VXI_TSTL,VXT_VAL,1,VXT_END,
+/* 472 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2bool,
+/* 480 */ VXT_END,
+/* 481 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2mint,
+/* 489 */ VXI_MOVL,VXT_REG,0x50,VXT_VAL,0,VXT_END,
+/* 495 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 503 */ SIZEOF(char *) * (short int)xf_commarg,VXT_END,
+/* 505 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVL,VXT_VAL,1,
+/* 513 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mint2mval,VXT_END,
+/* 519 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_mval2num,
+/* 527 */ VXT_END,
+/* 528 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 536 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_contain,VXT_END,
+/* 542 */ VXI_MOVL,VXT_REG,0x6C,VXT_ADDR,0,VXT_END,
+/* 548 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_currtn,
+/* 556 */ VXT_END,
+/* 557 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 565 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_cvtparm,VXT_END,
+/* 572 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 580 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_div,VXT_END,
+/* 587 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
+/* 595 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equ,VXT_END,
+/* 601 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_equnul,
+/* 609 */ VXT_END,
+/* 610 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 618 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_LIT,0,VXI_JSB,
+/* 626 */ VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
+/* 629 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 637 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_JSB,
+/* 645 */ VXT_XFER,SIZEOF(char *) * (short int)xf_exfun,VXT_END,
+/* 648 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunret,
+/* 656 */ VXT_END,
+/* 657 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_exfunretals,
+/* 665 */ VXT_END,
+/* 666 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 674 */ SIZEOF(char *) * (short int)xf_extcall,VXT_END,
+/* 676 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 684 */ 3,VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 692 */ VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
+/* 698 */ VXT_IREPAB,VXT_VAL,5,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 706 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 714 */ VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_extexfun,VXT_END,
+/* 720 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 728 */ SIZEOF(char *) * (short int)xf_extjmp,VXT_END,
+/* 730 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 738 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_exp,VXT_END,
+/* 745 */ VXT_IREPL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fetch,
+/* 753 */ VXT_END,
+/* 754 */ VXT_IREPAB,VXT_VAL,6,VXI_PUSHL,VXT_VAL,5,VXI_PUSHL,VXT_VAL,
+/* 762 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,
+/* 770 */ VXT_LIT,0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
+/* 778 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 786 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnascii,VXT_END,
+/* 793 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 801 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnchar,VXT_END,
+/* 805 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 813 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fndata,VXT_END,
+/* 817 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 825 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 833 */ SIZEOF(char *) * (short int)xf_fnextract,VXT_END,
+/* 835 */ VXT_IREPAB,VXT_VAL,6,VXI_PUSHL,VXT_VAL,5,VXI_PUSHL,VXT_VAL,
+/* 843 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 851 */ VXT_VAL,0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfgncal,VXT_END,
+/* 859 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 867 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 875 */ SIZEOF(char *) * (short int)xf_fnfind,VXT_END,
+/* 877 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 885 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 893 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnfnumber,VXT_END,
+/* 898 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
+/* 906 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget,VXT_END,
+/* 912 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 920 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget2,VXT_END,
+/* 927 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget,
+/* 935 */ VXT_END,
+/* 936 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fngvget1,
+/* 944 */ VXT_END,
+/* 945 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 953 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnget1,VXT_END,
+/* 957 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 965 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnincr,VXT_END,
+/* 972 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 980 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnj2,VXT_END,
+/* 987 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 995 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1003 */ SIZEOF(char *) * (short int)xf_fnj3,VXT_END,
+/* 1005 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1013 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlength,VXT_END,
+/* 1017 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1025 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvname,VXT_END,
+/* 1032 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
+/* 1040 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvnameo2,VXT_END,
+/* 1047 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1055 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnlvprvname,VXT_END,
+/* 1059 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 1067 */ 3,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,2,VXT_XFER,
+/* 1075 */ SIZEOF(char *) * (short int)xf_fnname,VXT_END,
+/* 1077 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1085 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnnext,VXT_END,
+/* 1092 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,
+/* 1100 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1108 */ SIZEOF(char *) * (short int)xf_fno2,VXT_END,
+/* 1110 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1118 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnorder,VXT_END,
+/* 1125 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1133 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1141 */ SIZEOF(char *) * (short int)xf_fnp1,VXT_END,
+/* 1143 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 1151 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1159 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpiece,VXT_END,
+/* 1164 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1172 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnpopulation,VXT_END,
+/* 1179 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1187 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqlength,VXT_END,
+/* 1191 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1199 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnqsubscript,VXT_END,
+/* 1206 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1214 */ 0,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnquery,VXT_END,
+/* 1221 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1229 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnrandom,VXT_END,
+/* 1233 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1241 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnreverse,VXT_END,
+/* 1245 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1253 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack1,VXT_END,
+/* 1257 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1265 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnstack2,VXT_END,
+/* 1272 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1280 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1288 */ SIZEOF(char *) * (short int)xf_fntext,VXT_END,
+/* 1290 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1298 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1306 */ SIZEOF(char *) * (short int)xf_fntranslate,VXT_END,
+/* 1308 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1316 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnview,VXT_END,
+/* 1320 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 1328 */ 2,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzascii,VXT_END,
+/* 1335 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1343 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzahandle,VXT_END,
+/* 1347 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1355 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitand,VXT_END,
+/* 1362 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1370 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitcoun,VXT_END,
+/* 1374 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1382 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1390 */ SIZEOF(char *) * (short int)xf_fnzbitfind,VXT_END,
+/* 1392 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1400 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitget,VXT_END,
+/* 1407 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1415 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitlen,VXT_END,
+/* 1419 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 1427 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitnot,VXT_END,
+/* 1431 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1439 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitor,VXT_END,
+/* 1446 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1454 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1462 */ SIZEOF(char *) * (short int)xf_fnzbitset,VXT_END,
+/* 1464 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1472 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitstr,VXT_END,
+/* 1479 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 1487 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzbitxor,VXT_END,
+/* 1494 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1502 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzcall,VXT_END,
+/* 1506 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1514 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzchar,VXT_END,
+/* 1518 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1526 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzconvert2,VXT_END,
+/* 1533 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1541 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1549 */ SIZEOF(char *) * (short int)xf_fnzconvert3,VXT_END,
+/* 1551 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1559 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdata,VXT_END,
+/* 1563 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
+/* 1571 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1579 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzdate,VXT_END,
+/* 1584 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHL,VXT_VAL,
+/* 1592 */ 2,VXI_PUSHL,VXT_VAL,3,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1600 */ SIZEOF(char *) * (short int)xf_fnzextract,VXT_END,
+/* 1602 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1610 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzfile,VXT_END,
+/* 1617 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1625 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1633 */ SIZEOF(char *) * (short int)xf_fnzfind,VXT_END,
+/* 1635 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1643 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetdvi,VXT_END,
+/* 1650 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1658 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetjpi,VXT_END,
+/* 1665 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1673 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetlki,VXT_END,
+/* 1680 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1688 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fngetsyi,VXT_END,
+/* 1695 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1703 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzj2,VXT_END,
+/* 1710 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1718 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzjobexam,VXT_END,
+/* 1722 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1730 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlength,VXT_END,
+/* 1734 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1742 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzlkid,VXT_END,
+/* 1746 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1754 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzm,VXT_END,
+/* 1758 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1766 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1774 */ SIZEOF(char *) * (short int)xf_fnzp1,VXT_END,
+/* 1776 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
+/* 1784 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 1792 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzparse,VXT_END,
+/* 1800 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1808 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpid,VXT_END,
+/* 1812 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 1820 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 1828 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpiece,VXT_END,
+/* 1833 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1841 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpopulation,VXT_END,
+/* 1848 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 1856 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzprevious,VXT_END,
+/* 1863 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1871 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpriv,VXT_END,
+/* 1875 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzqgblmod,
+/* 1883 */ VXT_END,
+/* 1884 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1892 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1900 */ SIZEOF(char *) * (short int)xf_fnzsearch,VXT_END,
+/* 1902 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 1910 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsetprv,VXT_END,
+/* 1914 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 1922 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsigproc,VXT_END,
+/* 1929 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_VAL,
+/* 1937 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsocket,VXT_END,
+/* 1941 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 1949 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1957 */ SIZEOF(char *) * (short int)xf_fnzsubstr,VXT_END,
+/* 1959 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1967 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1975 */ SIZEOF(char *) * (short int)xf_fnztranslate,VXT_END,
+/* 1977 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 1985 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 1993 */ SIZEOF(char *) * (short int)xf_fnztrigger,VXT_END,
+/* 1995 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,6,VXI_PUSHAB,VXT_VAL,
+/* 2003 */ 5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,
+/* 2011 */ VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,7,
+/* 2019 */ VXT_XFER,SIZEOF(char *) * (short int)xf_fnztrnlnm,VXT_END,
+/* 2022 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 2030 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwidth,VXT_END,
+/* 2034 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 2042 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_follow,VXT_END,
+/* 2048 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
+/* 2056 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forcenum,VXT_END,
+/* 2062 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forchk1,VXT_END,
+/* 2069 */ VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2077 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forinit,VXT_END,
+/* 2082 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldob,VXI_BRB,VXT_JMP,
/* 2090 */ 1,VXT_END,
-/* 2092 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 2100 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 2108 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 2111 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 2119 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 2127 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 2130 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
-/* 2138 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
-/* 2146 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
-/* 2149 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_getindx,
-/* 2157 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 2163 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_gettruth,
-/* 2171 */ VXT_END,
-/* 2172 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvdata,
-/* 2180 */ VXT_END,
-/* 2181 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2189 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvextnam,VXT_END,
-/* 2193 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvget,
-/* 2201 */ VXT_END,
-/* 2202 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 2210 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvincr,VXT_END,
-/* 2214 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvkill,VXT_END,
-/* 2220 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2228 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnaked,VXT_END,
-/* 2232 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2240 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvname,VXT_END,
-/* 2244 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnext,
-/* 2252 */ VXT_END,
-/* 2253 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 2261 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvo2,VXT_END,
-/* 2265 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvorder,
-/* 2273 */ VXT_END,
-/* 2274 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvput,
-/* 2282 */ VXT_END,
-/* 2283 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvquery,
-/* 2291 */ VXT_END,
-/* 2292 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvrectarg,
-/* 2300 */ VXT_END,
-/* 2301 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvsavtarg,
-/* 2309 */ VXT_END,
-/* 2310 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvzwithdraw,VXT_END,
-/* 2316 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 2324 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,
-/* 2332 */ SIZEOF(char *) * (short int)xf_gvzwrite,VXT_END,
-/* 2334 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_halt,VXT_END,
-/* 2340 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 2348 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_hang,VXT_END,
-/* 2352 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_hardret,VXT_END,
-/* 2356 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2364 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_idiv,VXT_END,
-/* 2371 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_igetsrc,
-/* 2379 */ VXT_END,
-/* 2380 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2388 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_inddevparms,VXT_END,
-/* 2393 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2401 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname,VXT_END,
-/* 2406 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2414 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfun,VXT_END,
-/* 2419 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2427 */ SIZEOF(char *) * (short int)xf_indglvn,VXT_END,
-/* 2429 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 2437 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indincr,VXT_END,
-/* 2442 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvadr,VXI_MOVL,VXT_REG,
-/* 2450 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2454 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2462 */ SIZEOF(char *) * (short int)xf_indlvarg,VXT_END,
-/* 2464 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,
-/* 2472 */ SIZEOF(char *) * (short int)xf_indmerge,VXT_END,
-/* 2474 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2482 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indname,VXT_END,
-/* 2489 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvnamadr,VXI_MOVL,VXT_REG,
-/* 2497 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2501 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2509 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indo2,VXT_END,
-/* 2516 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2524 */ SIZEOF(char *) * (short int)xf_indpat,VXT_END,
-/* 2526 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2534 */ SIZEOF(char *) * (short int)xf_indrzshow,VXT_END,
-/* 2536 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2544 */ SIZEOF(char *) * (short int)xf_indset,VXT_END,
-/* 2546 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2554 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indtext,VXT_END,
-/* 2562 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2570 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_iocontrol,VXT_END,
-/* 2574 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_iretmvad,
-/* 2582 */ VXT_END,
-/* 2583 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2591 */ SIZEOF(char *) * (short int)xf_iretmval,VXT_END,
-/* 2593 */ VXI_BRB,VXT_JMP,1,VXT_END,
-/* 2597 */ VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2601 */ VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2605 */ VXI_JMP,VXT_VAL,1,VXT_END,
-/* 2609 */ VXI_BEQL,VXT_JMP,1,VXT_END,
-/* 2613 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2620 */ VXI_BNEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2627 */ VXI_BGEQ,VXT_JMP,1,VXT_END,
-/* 2631 */ VXI_BLSS,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2638 */ VXI_BLSS,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2645 */ VXI_BGTR,VXT_JMP,1,VXT_END,
-/* 2649 */ VXI_BLEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2656 */ VXI_BLEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2663 */ VXI_BLEQ,VXT_JMP,1,VXT_END,
-/* 2667 */ VXI_BGTR,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2674 */ VXI_BGTR,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2681 */ VXI_BLSS,VXT_JMP,1,VXT_END,
-/* 2685 */ VXI_BGEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2692 */ VXI_BGEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2699 */ VXI_BNEQ,VXT_JMP,1,VXT_END,
-/* 2703 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
-/* 2710 */ VXI_BEQL,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
-/* 2717 */ VXI_BLBC,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
-/* 2723 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
-/* 2731 */ VXT_END,
-/* 2732 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
-/* 2740 */ VXT_END,
-/* 2741 */ VXI_BLBS,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
-/* 2747 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
-/* 2755 */ VXT_END,
-/* 2756 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
-/* 2764 */ VXT_END,
-/* 2765 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,7,VXI_PUSHL,VXT_VAL,
-/* 2773 */ 6,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,
-/* 2781 */ VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,
-/* 2789 */ VXT_XFER,SIZEOF(char *) * (short int)xf_job,VXT_END,
-/* 2792 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_kill,
-/* 2800 */ VXT_END,
-/* 2801 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_killalias,
-/* 2809 */ VXT_END,
-/* 2810 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killall,VXT_END,
-/* 2816 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killaliasall,VXT_END,
-/* 2822 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 2830 */ 3,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_labaddr,VXI_MOVL,VXT_REG,
-/* 2838 */ 0x50,VXT_ADDR,0,VXT_END,
-/* 2842 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckdecr,
-/* 2850 */ VXT_END,
-/* 2851 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckincr,
-/* 2859 */ VXT_END,
-/* 2860 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2866 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2872 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
-/* 2878 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 2886 */ SIZEOF(char *) * (short int)xf_linefetch,VXT_END,
-/* 2888 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_linestart,VXT_END,
-/* 2892 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 2900 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
-/* 2907 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_lkinit,VXT_END,
-/* 2913 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2921 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
-/* 2928 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lock,
-/* 2936 */ VXT_END,
-/* 2937 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 2945 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvpatwrite,VXT_END,
-/* 2952 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwithdraw,
-/* 2960 */ VXT_END,
-/* 2961 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 2969 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwrite,VXT_END,
-/* 2973 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_m_srchindx,
-/* 2981 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 2987 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_merge,VXT_END,
-/* 2993 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3001 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
-/* 3005 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3013 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
-/* 3017 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3025 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_flt_mod,VXT_END,
-/* 3032 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3040 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_mul,VXT_END,
-/* 3047 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
-/* 3055 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_neg,VXT_END,
-/* 3061 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newintrinsic,VXT_END,
-/* 3068 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newvar,VXT_END,
-/* 3075 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_nullexp,VXI_MOVL,VXT_REG,0x50,
-/* 3083 */ VXT_ADDR,0,VXT_END,
-/* 3086 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 3094 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_numcmp,VXT_END,
-/* 3100 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3108 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3116 */ VXT_LIT,4,VXT_XFER,SIZEOF(char *) * (short int)xf_open,VXT_END,
-/* 3121 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 3129 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_pattern,VXT_END,
-/* 3135 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_putindx,
-/* 3143 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 3149 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 3157 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_rdone,VXT_END,
-/* 3164 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 3172 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_read,VXT_END,
-/* 3179 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
-/* 3187 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,3,VXT_XFER,
-/* 3195 */ SIZEOF(char *) * (short int)xf_readfl,VXT_END,
-/* 3197 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_END,
-/* 3201 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_ret,VXT_END,
-/* 3205 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVL,VXT_VAL,2,
-/* 3213 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_retarg,VXT_END,
-/* 3219 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3227 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 3235 */ VXT_END,
-/* 3236 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3244 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 3252 */ VXT_END,
-/* 3253 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3261 */ SIZEOF(char *) * (short int)xf_rterror,VXT_END,
-/* 3263 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3271 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setals2als,VXT_END,
-/* 3275 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3283 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsin2alsct,VXT_END,
-/* 3287 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3295 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsctin2als,VXT_END,
-/* 3299 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3307 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsct2alsct,VXT_END,
-/* 3311 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3319 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2als,VXT_END,
-/* 3323 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
-/* 3331 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2alsct,VXT_END,
-/* 3335 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3343 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3351 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setextract,VXT_END,
-/* 3356 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3364 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3372 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setp1,VXT_END,
-/* 3377 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3385 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3393 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setpiece,VXT_END,
-/* 3401 */ VXI_BISB2,VXT_LIT,1,VXT_REG,0x5A,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_dt_true,
-/* 3409 */ VXT_END,
-/* 3410 */ VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3418 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,3,VXI_CALLS,
-/* 3426 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzbrk,VXT_END,
-/* 3431 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
-/* 3439 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3447 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzextract,VXT_END,
-/* 3452 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3460 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 3468 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzp1,VXT_END,
-/* 3473 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 3481 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3489 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setzpiece,VXT_END,
-/* 3497 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
-/* 3505 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sorts_after,VXT_END,
-/* 3511 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_srchindx,
-/* 3519 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 3525 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
-/* 3533 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
-/* 3539 */ VXI_MOVC3,VXT_LIT,16,VXT_VAL,2,VXT_VAL,1,VXT_END,
-/* 3547 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
-/* 3555 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
-/* 3561 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3569 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_sub,VXT_END,
-/* 3576 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3584 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svget,VXT_END,
-/* 3588 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3596 */ SIZEOF(char *) * (short int)xf_psvput,VXT_END,
-/* 3598 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3606 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svput,VXT_END,
-/* 3610 */ VXI_MOVL,VXT_REG,0x50,VXT_REG,0x5A,VXT_END,
-/* 3616 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tcommit,VXT_END,
-/* 3620 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trollback,VXT_END,
-/* 3627 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trestart,VXT_END,
-/* 3634 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
-/* 3642 */ 2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tstart,VXT_END,
-/* 3650 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_unlock,VXT_END,
-/* 3656 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3664 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_use,VXT_END,
-/* 3668 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_view,
-/* 3676 */ VXT_END,
-/* 3677 */ VXI_CMPL,VXT_VAL,1,VXT_VAL,2,VXT_END,
-/* 3683 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_write,
-/* 3691 */ VXT_END,
-/* 3692 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wteol,
-/* 3700 */ VXT_END,
-/* 3701 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_wtff,VXT_END,
-/* 3707 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wtone,
-/* 3715 */ VXT_END,
-/* 3716 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wttab,
-/* 3724 */ VXT_END,
-/* 3725 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_xkill,
+/* 2092 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldol,VXI_JMP,VXT_JMP,
+/* 2100 */ 1,VXT_END,
+/* 2102 */ VXI_PUSHL,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_forlcldow,VXI_BRW,VXT_JMP,
+/* 2110 */ 1,VXT_END,
+/* 2112 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 2120 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 2128 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2131 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 2139 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 2147 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2150 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_JMP,1,VXI_PUSHAB,VXT_VAL,
+/* 2158 */ 4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,
+/* 2166 */ VXT_XFER,SIZEOF(char *) * (short int)xf_forloop,VXT_END,
+/* 2169 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_getindx,
+/* 2177 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 2183 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_gettruth,
+/* 2191 */ VXT_END,
+/* 2192 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvdata,
+/* 2200 */ VXT_END,
+/* 2201 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2209 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvextnam,VXT_END,
+/* 2213 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvget,
+/* 2221 */ VXT_END,
+/* 2222 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 2230 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvincr,VXT_END,
+/* 2234 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvkill,VXT_END,
+/* 2240 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2248 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnaked,VXT_END,
+/* 2252 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2260 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvname,VXT_END,
+/* 2264 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvnext,
+/* 2272 */ VXT_END,
+/* 2273 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 2281 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_gvo2,VXT_END,
+/* 2285 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvorder,
+/* 2293 */ VXT_END,
+/* 2294 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvput,
+/* 2302 */ VXT_END,
+/* 2303 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvquery,
+/* 2311 */ VXT_END,
+/* 2312 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvrectarg,
+/* 2320 */ VXT_END,
+/* 2321 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_gvsavtarg,
+/* 2329 */ VXT_END,
+/* 2330 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_gvzwithdraw,VXT_END,
+/* 2336 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 2344 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,
+/* 2352 */ SIZEOF(char *) * (short int)xf_gvzwrite,VXT_END,
+/* 2354 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_halt,VXT_END,
+/* 2360 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 2368 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_hang,VXT_END,
+/* 2372 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_hardret,VXT_END,
+/* 2376 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2384 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_idiv,VXT_END,
+/* 2391 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_igetsrc,
+/* 2399 */ VXT_END,
+/* 2400 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2408 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_inddevparms,VXT_END,
+/* 2413 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2421 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname,VXT_END,
+/* 2426 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2434 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indfun,VXT_END,
+/* 2439 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2447 */ SIZEOF(char *) * (short int)xf_indglvn,VXT_END,
+/* 2449 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 2457 */ 0,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indincr,VXT_END,
+/* 2462 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvadr,VXI_MOVL,VXT_REG,
+/* 2470 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2474 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2482 */ SIZEOF(char *) * (short int)xf_indlvarg,VXT_END,
+/* 2484 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,
+/* 2492 */ SIZEOF(char *) * (short int)xf_indmerge,VXT_END,
+/* 2494 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2502 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indname,VXT_END,
+/* 2509 */ VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indlvnamadr,VXI_MOVL,VXT_REG,
+/* 2517 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2521 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2529 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indo2,VXT_END,
+/* 2536 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2544 */ SIZEOF(char *) * (short int)xf_indpat,VXT_END,
+/* 2546 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2554 */ SIZEOF(char *) * (short int)xf_indrzshow,VXT_END,
+/* 2556 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2564 */ SIZEOF(char *) * (short int)xf_indset,VXT_END,
+/* 2566 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2574 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indtext,VXT_END,
+/* 2582 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2590 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_iocontrol,VXT_END,
+/* 2594 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_iretmvad,
+/* 2602 */ VXT_END,
+/* 2603 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2611 */ SIZEOF(char *) * (short int)xf_iretmval,VXT_END,
+/* 2613 */ VXI_BRB,VXT_JMP,1,VXT_END,
+/* 2617 */ VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2621 */ VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2625 */ VXI_JMP,VXT_VAL,1,VXT_END,
+/* 2629 */ VXI_BEQL,VXT_JMP,1,VXT_END,
+/* 2633 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2640 */ VXI_BNEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2647 */ VXI_BGEQ,VXT_JMP,1,VXT_END,
+/* 2651 */ VXI_BLSS,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2658 */ VXI_BLSS,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2665 */ VXI_BGTR,VXT_JMP,1,VXT_END,
+/* 2669 */ VXI_BLEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2676 */ VXI_BLEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2683 */ VXI_BLEQ,VXT_JMP,1,VXT_END,
+/* 2687 */ VXI_BGTR,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2694 */ VXI_BGTR,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2701 */ VXI_BLSS,VXT_JMP,1,VXT_END,
+/* 2705 */ VXI_BGEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2712 */ VXI_BGEQ,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2719 */ VXI_BNEQ,VXT_JMP,1,VXT_END,
+/* 2723 */ VXI_BNEQ,VXT_LIT,6,VXI_JMP,VXT_JMP,1,VXT_END,
+/* 2730 */ VXI_BEQL,VXT_LIT,3,VXI_BRW,VXT_JMP,1,VXT_END,
+/* 2737 */ VXI_BLBC,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
+/* 2743 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
+/* 2751 */ VXT_END,
+/* 2752 */ VXI_BLBS,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
+/* 2760 */ VXT_END,
+/* 2761 */ VXI_BLBS,VXT_REG,0x5A,VXT_JMP,1,VXT_END,
+/* 2767 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,6,VXI_JMP,VXT_JMP,1,
+/* 2775 */ VXT_END,
+/* 2776 */ VXI_BLBC,VXT_REG,0x5A,VXT_LIT,3,VXI_BRW,VXT_JMP,1,
+/* 2784 */ VXT_END,
+/* 2785 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,7,VXI_PUSHL,VXT_VAL,
+/* 2793 */ 6,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,
+/* 2801 */ VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,
+/* 2809 */ VXT_XFER,SIZEOF(char *) * (short int)xf_job,VXT_END,
+/* 2812 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_kill,
+/* 2820 */ VXT_END,
+/* 2821 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_killalias,
+/* 2829 */ VXT_END,
+/* 2830 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killall,VXT_END,
+/* 2836 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_killaliasall,VXT_END,
+/* 2842 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 2850 */ 3,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_labaddr,VXI_MOVL,VXT_REG,
+/* 2858 */ 0x50,VXT_ADDR,0,VXT_END,
+/* 2862 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckdecr,
+/* 2870 */ VXT_END,
+/* 2871 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lckincr,
+/* 2879 */ VXT_END,
+/* 2880 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2886 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2892 */ VXI_MOVAB,VXT_JMP,1,VXT_ADDR,0,VXT_END,
+/* 2898 */ VXT_IREPL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 2906 */ SIZEOF(char *) * (short int)xf_linefetch,VXT_END,
+/* 2908 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_linestart,VXT_END,
+/* 2912 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 2920 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
+/* 2927 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_lkinit,VXT_END,
+/* 2933 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2941 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lkname,VXT_END,
+/* 2948 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lock,
+/* 2956 */ VXT_END,
+/* 2957 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 2965 */ 2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvpatwrite,VXT_END,
+/* 2972 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwithdraw,
+/* 2980 */ VXT_END,
+/* 2981 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 2989 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_lvzwrite,VXT_END,
+/* 2993 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_m_srchindx,
+/* 3001 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3007 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_merge,VXT_END,
+/* 3013 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3021 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
+/* 3025 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3033 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_merge_arg,VXT_END,
+/* 3037 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3045 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_flt_mod,VXT_END,
+/* 3052 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3060 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_mul,VXT_END,
+/* 3067 */ VXI_MOVAB,VXT_VAL,0,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,1,
+/* 3075 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_neg,VXT_END,
+/* 3081 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newintrinsic,VXT_END,
+/* 3088 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_newvar,VXT_END,
+/* 3095 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_nullexp,VXI_MOVL,VXT_REG,0x50,
+/* 3103 */ VXT_ADDR,0,VXT_END,
+/* 3106 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 3114 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_numcmp,VXT_END,
+/* 3120 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3128 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3136 */ VXT_LIT,4,VXT_XFER,SIZEOF(char *) * (short int)xf_open,VXT_END,
+/* 3141 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 3149 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_pattern,VXT_END,
+/* 3155 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_putindx,
+/* 3163 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3169 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 3177 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_rdone,VXT_END,
+/* 3184 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 3192 */ 0,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_read,VXT_END,
+/* 3199 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,
+/* 3207 */ 1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,3,VXT_XFER,
+/* 3215 */ SIZEOF(char *) * (short int)xf_readfl,VXT_END,
+/* 3217 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXT_END,
+/* 3221 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_ret,VXT_END,
+/* 3225 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVL,VXT_VAL,2,
+/* 3233 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_retarg,VXT_END,
+/* 3239 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3247 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 3255 */ VXT_END,
+/* 3256 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3264 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rhdaddr,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 3272 */ VXT_END,
+/* 3273 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3281 */ SIZEOF(char *) * (short int)xf_rterror,VXT_END,
+/* 3283 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3291 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setals2als,VXT_END,
+/* 3295 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3303 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsin2alsct,VXT_END,
+/* 3307 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3315 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsctin2als,VXT_END,
+/* 3319 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3327 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setalsct2alsct,VXT_END,
+/* 3331 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3339 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2als,VXT_END,
+/* 3343 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,2,VXI_CALLS,VXT_LIT,
+/* 3351 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_setfnretin2alsct,VXT_END,
+/* 3355 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3363 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3371 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setextract,VXT_END,
+/* 3376 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3384 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3392 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setp1,VXT_END,
+/* 3397 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3405 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3413 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setpiece,VXT_END,
+/* 3421 */ VXI_BISB2,VXT_LIT,1,VXT_REG,0x5A,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_dt_true,
+/* 3429 */ VXT_END,
+/* 3430 */ VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3438 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,3,VXI_JSB,
+/* 3446 */ VXT_XFER,SIZEOF(char *) * (short int)xf_setzbrk,VXT_END,
+/* 3449 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3457 */ 2,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3465 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzextract,VXT_END,
+/* 3470 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3478 */ 4,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 3486 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_setzp1,VXT_END,
+/* 3491 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 3499 */ 3,VXI_PUSHAB,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3507 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,6,VXT_XFER,SIZEOF(char *) * (short int)xf_setzpiece,VXT_END,
+/* 3515 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x50,VXI_MOVAB,VXT_VAL,2,
+/* 3523 */ VXT_REG,0x51,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sorts_after,VXT_END,
+/* 3529 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_srchindx,
+/* 3537 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 3543 */ VXI_MOVAB,VXT_VAL,2,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,1,
+/* 3551 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
+/* 3557 */ VXI_MOVC3,VXT_LIT,16,VXT_VAL,2,VXT_VAL,1,VXT_END,
+/* 3565 */ VXI_MOVAB,VXT_VAL,1,VXT_REG,0x51,VXI_MOVAB,VXT_VAL,0,
+/* 3573 */ VXT_REG,0x50,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_sto,VXT_END,
+/* 3579 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3587 */ 1,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_sub,VXT_END,
+/* 3594 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3602 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svget,VXT_END,
+/* 3606 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3614 */ SIZEOF(char *) * (short int)xf_psvput,VXT_END,
+/* 3616 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3624 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_svput,VXT_END,
+/* 3628 */ VXI_MOVL,VXT_REG,0x50,VXT_REG,0x5A,VXT_END,
+/* 3634 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tcommit,VXT_END,
+/* 3638 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trollback,VXT_END,
+/* 3645 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_trestart,VXT_END,
+/* 3652 */ VXT_IREPAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 3660 */ 2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_tstart,VXT_END,
+/* 3668 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_unlock,VXT_END,
+/* 3674 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3682 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_use,VXT_END,
+/* 3686 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_view,
+/* 3694 */ VXT_END,
+/* 3695 */ VXI_CMPL,VXT_VAL,1,VXT_VAL,2,VXT_END,
+/* 3701 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_write,
+/* 3709 */ VXT_END,
+/* 3710 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wteol,
+/* 3718 */ VXT_END,
+/* 3719 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_wtff,VXT_END,
+/* 3725 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wtone,
/* 3733 */ VXT_END,
-/* 3734 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 3742 */ SIZEOF(char *) * (short int)xf_xnew,VXT_END,
-/* 3744 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zallocate,
-/* 3752 */ VXT_END,
-/* 3753 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3761 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zattach,VXT_END,
-/* 3765 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3773 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zcompile,VXT_END,
-/* 3777 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3781 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zdeallocate,
-/* 3789 */ VXT_END,
-/* 3790 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 3798 */ 1,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_zedit,VXT_END,
-/* 3805 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zg1,VXT_END,
-/* 3812 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHL,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
-/* 3820 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zgoto,VXT_END,
-/* 3828 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zhalt,
-/* 3836 */ VXT_END,
-/* 3837 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3845 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zhelp,VXT_END,
-/* 3849 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3857 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zlink,VXT_END,
-/* 3861 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 3869 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zmess,VXT_END,
-/* 3873 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zprevious,
-/* 3881 */ VXT_END,
-/* 3882 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
-/* 3890 */ 4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
-/* 3898 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_zprint,VXT_END,
-/* 3906 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,
-/* 3914 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
-/* 3922 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
-/* 3924 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3734 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_wttab,
+/* 3742 */ VXT_END,
+/* 3743 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_xkill,
+/* 3751 */ VXT_END,
+/* 3752 */ VXT_IREPAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 3760 */ SIZEOF(char *) * (short int)xf_xnew,VXT_END,
+/* 3762 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zallocate,
+/* 3770 */ VXT_END,
+/* 3771 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3779 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zattach,VXT_END,
+/* 3783 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3791 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zcompile,VXT_END,
+/* 3795 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3799 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zdeallocate,
+/* 3807 */ VXT_END,
+/* 3808 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 3816 */ 1,VXI_CALLS,VXT_LIT,2,VXT_XFER,SIZEOF(char *) * (short int)xf_zedit,VXT_END,
+/* 3823 */ VXI_PUSHL,VXT_VAL,1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zg1,VXT_END,
+/* 3830 */ VXI_PUSHL,VXT_VAL,1,VXI_PUSHL,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,
+/* 3838 */ 3,VXI_PUSHAB,VXT_VAL,2,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zgoto,VXT_END,
+/* 3846 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zhalt,
+/* 3854 */ VXT_END,
+/* 3855 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3863 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zhelp,VXT_END,
+/* 3867 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3875 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zlink,VXT_END,
+/* 3879 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 3887 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zmess,VXT_END,
+/* 3891 */ VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zprevious,
+/* 3899 */ VXT_END,
+/* 3900 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_VAL,5,VXI_PUSHAB,VXT_VAL,
+/* 3908 */ 4,VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,
+/* 3916 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_zprint,VXT_END,
+/* 3924 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,
/* 3932 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
/* 3940 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
-/* 3942 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3950 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3957 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3965 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
-/* 3972 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 3980 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zsystem,VXT_END,
-/* 3984 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_ztcommit,
-/* 3992 */ VXT_END,
-/* 3993 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztrigger,VXT_END,
-/* 3999 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztstart,VXT_END,
-/* 4005 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zwritesvn,
-/* 4013 */ VXT_END,
-/* 4014 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4022 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwrite,VXT_END,
-/* 4026 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_igetdst,VXI_MOVL,VXT_REG,0x50,
-/* 4034 */ VXT_ADDR,0,VXT_END,
-/* 4037 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4045 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget1,VXT_END,
-/* 4049 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnpop,
-/* 4057 */ VXT_END,
-/* 4058 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnslot,
-/* 4066 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
-/* 4072 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
-/* 4080 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indsavglvn,VXT_END,
-/* 4085 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
-/* 4093 */ SIZEOF(char *) * (short int)xf_indsavlvn,VXT_END,
-/* 4095 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4103 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshlvn,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
-/* 4111 */ VXT_END,
-/* 4112 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
-/* 4120 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_savgvn,VXT_END,
-/* 4124 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_savlvn,
-/* 4132 */ VXT_END,
-/* 4133 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4141 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_shareslot,VXT_END,
-/* 4145 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4153 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_stoglvn,VXT_END,
-/* 4157 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
-/* 4165 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshgvn,VXT_END,
-/* 4169 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
-/* 4177 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname2,VXT_END,
-/* 4184 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 4192 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget2,VXT_END,
-/* 4196 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_indmerge2,
-/* 4204 */ VXT_END,
-/* 4205 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
-/* 4213 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_litc,VXT_END,
-/* 4217 */ VXI_MOVC3,VXT_LIT,16,VXT_VAL,2,VXT_VAL,1,VXI_PUSHAB,
-/* 4225 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_stolitc,VXT_END,
-/* 4233 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
-/* 4241 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
-/* 4249 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpeek,VXT_END,
-/* 4254 */ 361,381,371,2593,2601,2597,2860,2872,
-/* 4262 */ 2866,0,0,0,500,476,467,0,
-/* 4270 */ 0,463,2092,2130,2111,2741,2756,2747,
-/* 4278 */ 2717,2732,2723,2609,2620,2613,2699,2710,
-/* 4286 */ 2703,2645,2656,2649,2663,2674,2667,2681,
-/* 4294 */ 2692,2685,2627,2638,2631,2062,2082,2072,
-/* 4302 */ 391,411,401};
+/* 3942 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,
+/* 3950 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,3,VXT_XFER,
+/* 3958 */ SIZEOF(char *) * (short int)xf_zshow,VXT_END,
+/* 3960 */ VXI_PUSHL,VXT_LIT,0,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3968 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3975 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3983 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_zstep,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_zcont,VXT_END,
+/* 3990 */ VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_restartpc,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 3998 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_zsystem,VXT_END,
+/* 4002 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_ztcommit,
+/* 4010 */ VXT_END,
+/* 4011 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztrigger,VXT_END,
+/* 4017 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_ztstart,VXT_END,
+/* 4023 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zwritesvn,
+/* 4031 */ VXT_END,
+/* 4032 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4040 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzwrite,VXT_END,
+/* 4044 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_igetdst,VXI_MOVL,VXT_REG,0x50,
+/* 4052 */ VXT_ADDR,0,VXT_END,
+/* 4055 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4063 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget1,VXT_END,
+/* 4067 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnpop,
+/* 4075 */ VXT_END,
+/* 4076 */ VXI_PUSHL,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_glvnslot,
+/* 4084 */ VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 4090 */ VXI_PUSHL,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,
+/* 4098 */ 1,VXI_JSB,VXT_XFER,SIZEOF(char *) * (short int)xf_indsavglvn,VXT_END,
+/* 4103 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_JSB,VXT_XFER,
+/* 4111 */ SIZEOF(char *) * (short int)xf_indsavlvn,VXT_END,
+/* 4113 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4121 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshlvn,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,
+/* 4129 */ VXT_END,
+/* 4130 */ VXT_IREPAB,VXT_VAL,3,VXI_PUSHL,VXT_VAL,2,VXI_CALLS,VXT_VAL,
+/* 4138 */ 1,VXT_XFER,SIZEOF(char *) * (short int)xf_savgvn,VXT_END,
+/* 4142 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_savlvn,
+/* 4150 */ VXT_END,
+/* 4151 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4159 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_shareslot,VXT_END,
+/* 4163 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4171 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_stoglvn,VXT_END,
+/* 4175 */ VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4183 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_rfrshgvn,VXT_END,
+/* 4187 */ VXI_PUSHAB,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,
+/* 4195 */ 0,VXI_CALLS,VXT_LIT,3,VXT_XFER,SIZEOF(char *) * (short int)xf_indfnname2,VXT_END,
+/* 4202 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 4210 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_indget2,VXT_END,
+/* 4214 */ VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_indmerge2,
+/* 4222 */ VXT_END,
+/* 4223 */ VXI_PUSHAB,VXT_VAL,1,VXI_PUSHAB,VXT_VAL,0,VXI_CALLS,VXT_LIT,
+/* 4231 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_litc,VXT_END,
+/* 4235 */ VXI_MOVC3,VXT_LIT,16,VXT_VAL,2,VXT_VAL,1,VXI_PUSHAB,
+/* 4243 */ VXT_VAL,1,VXI_CALLS,VXT_LIT,1,VXT_XFER,SIZEOF(char *) * (short int)xf_stolitc,VXT_END,
+/* 4251 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,4,VXI_PUSHL,VXT_VAL,
+/* 4259 */ 3,VXI_PUSHL,VXT_VAL,2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,
+/* 4267 */ VXT_LIT,5,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzpeek,VXT_END,
+/* 4272 */ VXI_PUSHAB,VXT_VAL,0,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,
+/* 4280 */ 2,VXT_XFER,SIZEOF(char *) * (short int)xf_fnzsyslog,VXT_END,
+/* 4284 */ VXI_PUSHAB,VXT_VAL,4,VXI_PUSHAB,VXT_VAL,3,VXI_PUSHAB,VXT_VAL,
+/* 4292 */ 2,VXI_PUSHAB,VXT_VAL,1,VXI_CALLS,VXT_LIT,4,VXT_XFER,
+/* 4300 */ SIZEOF(char *) * (short int)xf_rhd_ext,VXI_MOVL,VXT_REG,0x50,VXT_ADDR,0,VXT_END,
+/* 4307 */ VXI_CALLS,VXT_LIT,0,VXT_XFER,SIZEOF(char *) * (short int)xf_lab_ext,VXI_MOVL,VXT_REG,0x50,
+/* 4315 */ VXT_ADDR,0,VXT_END,
+/* 4318 */ VXT_IREPAB,VXT_VAL,2,VXI_CALLS,VXT_VAL,1,VXT_XFER,SIZEOF(char *) * (short int)xf_zrupdate,
+/* 4326 */ VXT_END,
+/* 4327 */ 366,386,376,2613,2621,2617,2880,2892,
+/* 4335 */ 2886,0,0,0,505,481,472,0,
+/* 4343 */ 0,468,2112,2150,2131,2761,2776,2767,
+/* 4351 */ 2737,2752,2743,2629,2640,2633,2719,2730,
+/* 4359 */ 2723,2665,2676,2669,2683,2694,2687,2701,
+/* 4367 */ 2712,2705,2647,2658,2651,2082,2102,2092,
+/* 4375 */ 396,416,406};
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/fis-gtm.git
More information about the debian-med-commit
mailing list